From 071bcd9ccd4d37aac29c11fd3846ca4d744b39ad Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:25:50 +1200 Subject: [PATCH 01/18] fix(stripe): add ConnectedAccountHandler to resolve missing handler error --- stripe/stripe.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index 9351784d..c5767347 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -1,10 +1,39 @@ -from autohive_integrations_sdk import Integration, ExecutionContext, ActionHandler, ActionResult +from autohive_integrations_sdk import ( + Integration, + ExecutionContext, + ActionHandler, + ActionResult, + ConnectedAccountHandler, + ConnectedAccountInfo, +) from typing import Dict, Any # Load integration from config.json stripe = Integration.load() + +@stripe.connected_account() +class StripeConnectedAccountHandler(ConnectedAccountHandler): + async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountInfo: + try: + response = await context.fetch( + f"{STRIPE_API_BASE_URL}/{API_VERSION}/account", + method="GET", + headers=get_common_headers(), + ) + data = response.data or {} + email = data.get("email") or data.get("business_profile", {}).get("support_email", "") + name = ( + data.get("business_profile", {}).get("name") + or data.get("display_name") + or email + or "Stripe Account" + ) + return ConnectedAccountInfo(username=name, user_id=data.get("id")) + except Exception: + return ConnectedAccountInfo(username="Stripe Account") + # Base URL for Stripe API STRIPE_API_BASE_URL = "https://api.stripe.com" API_VERSION = "v1" From e053ee3fa3b144ab87de533c03a782f84446e9be Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:26:57 +1200 Subject: [PATCH 02/18] chore(stripe): bump version to 2.1.0 --- stripe/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stripe/config.json b/stripe/config.json index 8f756131..1cb23aed 100644 --- a/stripe/config.json +++ b/stripe/config.json @@ -1,7 +1,7 @@ { "name": "Stripe", "display_name": "Stripe", - "version": "2.0.0", + "version": "2.1.0", "description": "Stripe integration for managing customers, invoices, products, prices, subscriptions, payment methods and invoice items via the Stripe API", "entry_point": "stripe.py", "supports_billing": true, From b2b4d8afed37933e644b0200adaecc29d063abac Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:27:23 +1200 Subject: [PATCH 03/18] style(stripe): ruff format --- stripe/stripe.py | 492 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 392 insertions(+), 100 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index c5767347..342c2c50 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -23,7 +23,9 @@ async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountI headers=get_common_headers(), ) data = response.data or {} - email = data.get("email") or data.get("business_profile", {}).get("support_email", "") + email = data.get("email") or data.get("business_profile", {}).get( + "support_email", "" + ) name = ( data.get("business_profile", {}).get("name") or data.get("display_name") @@ -34,6 +36,7 @@ async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountI except Exception: return ConnectedAccountInfo(username="Stripe Account") + # Base URL for Stripe API STRIPE_API_BASE_URL = "https://api.stripe.com" API_VERSION = "v1" @@ -47,7 +50,10 @@ def get_common_headers() -> Dict[str, str]: Return common headers for Stripe API requests. Auth headers are automatically added by the SDK when using platform auth. """ - return {"Content-Type": "application/x-www-form-urlencoded", "Stripe-Version": "2025-12-15.preview"} + return { + "Content-Type": "application/x-www-form-urlencoded", + "Stripe-Version": "2025-12-15.preview", + } def build_form_data(data: Dict[str, Any], prefix: str = "") -> Dict[str, str]: @@ -119,18 +125,32 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", + method="GET", + headers=headers, + params=params, ) customers = response.get("data", []) return ActionResult( - data={"customers": customers, "has_more": response.get("has_more", False), "result": True}, cost_usd=0.0 + data={ + "customers": customers, + "has_more": response.get("has_more", False), + "result": True, + }, + cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"customers": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "customers": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -144,13 +164,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", + method="GET", + headers=headers, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("create_customer") @@ -179,13 +205,20 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", + method="POST", + headers=headers, + data=form_data, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("update_customer") @@ -221,10 +254,14 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("delete_customer") @@ -237,17 +274,28 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="DELETE", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", + method="DELETE", + headers=headers, ) return ActionResult( - data={"id": response.get("id", customer_id), "deleted": response.get("deleted", True), "result": True}, + data={ + "id": response.get("id", customer_id), + "deleted": response.get("deleted", True), + "result": True, + }, cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"id": inputs.get("customer_id", ""), "deleted": False, "result": False, "error": str(e)}, + data={ + "id": inputs.get("customer_id", ""), + "deleted": False, + "result": False, + "error": str(e), + }, cost_usd=0.0, ) @@ -276,18 +324,32 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", + method="GET", + headers=headers, + params=params, ) invoices = response.get("data", []) return ActionResult( - data={"invoices": invoices, "has_more": response.get("has_more", False), "result": True}, cost_usd=0.0 + data={ + "invoices": invoices, + "has_more": response.get("has_more", False), + "result": True, + }, + cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"invoices": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "invoices": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -301,13 +363,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", + method="GET", + headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("create_invoice") @@ -336,13 +404,20 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", + method="POST", + headers=headers, + data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("update_invoice") @@ -376,10 +451,14 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("delete_invoice") @@ -392,17 +471,28 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="DELETE", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", + method="DELETE", + headers=headers, ) return ActionResult( - data={"id": response.get("id", invoice_id), "deleted": response.get("deleted", True), "result": True}, + data={ + "id": response.get("id", invoice_id), + "deleted": response.get("deleted", True), + "result": True, + }, cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"id": inputs.get("invoice_id", ""), "deleted": False, "result": False, "error": str(e)}, + data={ + "id": inputs.get("invoice_id", ""), + "deleted": False, + "result": False, + "error": str(e), + }, cost_usd=0.0, ) @@ -429,10 +519,14 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("send_invoice") @@ -445,13 +539,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/send", method="POST", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/send", + method="POST", + headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("pay_invoice") @@ -476,10 +576,14 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("void_invoice") @@ -492,13 +596,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/void", method="POST", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/void", + method="POST", + headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) # ---- Invoice Item Action Handlers ---- @@ -523,19 +633,32 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", + method="GET", + headers=headers, + params=params, ) invoice_items = response.get("data", []) return ActionResult( - data={"invoice_items": invoice_items, "has_more": response.get("has_more", False), "result": True}, + data={ + "invoice_items": invoice_items, + "has_more": response.get("has_more", False), + "result": True, + }, cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"invoice_items": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "invoice_items": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -549,13 +672,20 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", + method="GET", + headers=headers, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice_item": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("create_invoice_item") @@ -586,13 +716,21 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", + method="POST", + headers=headers, + data=form_data, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice_item": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("update_invoice_item") @@ -626,10 +764,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"invoice_item": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("delete_invoice_item") @@ -642,7 +785,9 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="DELETE", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", + method="DELETE", + headers=headers, ) return ActionResult( @@ -656,7 +801,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): except Exception as e: return ActionResult( - data={"id": inputs.get("invoice_item_id", ""), "deleted": False, "result": False, "error": str(e)}, + data={ + "id": inputs.get("invoice_item_id", ""), + "deleted": False, + "result": False, + "error": str(e), + }, cost_usd=0.0, ) @@ -685,18 +835,32 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", + method="GET", + headers=headers, + params=params, ) products = response.get("data", []) return ActionResult( - data={"products": products, "has_more": response.get("has_more", False), "result": True}, cost_usd=0.0 + data={ + "products": products, + "has_more": response.get("has_more", False), + "result": True, + }, + cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"products": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "products": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -710,13 +874,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", + method="GET", + headers=headers, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("create_product") @@ -749,13 +919,20 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", + method="POST", + headers=headers, + data=form_data, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("update_product") @@ -797,10 +974,14 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) # ---- Price Action Handlers ---- @@ -831,17 +1012,33 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", + method="GET", + headers=headers, + params=params, ) prices = response.get("data", []) return ActionResult( - data={"prices": prices, "has_more": response.get("has_more", False), "result": True}, cost_usd=0.0 + data={ + "prices": prices, + "has_more": response.get("has_more", False), + "result": True, + }, + cost_usd=0.0, ) except Exception as e: - return ActionResult(data={"prices": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={ + "prices": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, + ) @stripe.action("get_price") @@ -854,13 +1051,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", + method="GET", + headers=headers, ) return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("create_price") @@ -869,7 +1070,10 @@ class CreatePriceAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - body = {"currency": inputs.get("currency", "usd"), "product": inputs["product"]} + body = { + "currency": inputs.get("currency", "usd"), + "product": inputs["product"], + } # Add unit_amount or custom_unit_amount if "unit_amount" in inputs and inputs["unit_amount"] is not None: @@ -899,13 +1103,18 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", + method="POST", + headers=headers, + data=form_data, ) return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) @stripe.action("update_price") @@ -931,13 +1140,18 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", + method="POST", + headers=headers, + data=form_data, ) return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 + ) # ---- Subscription Action Handlers ---- @@ -962,27 +1176,46 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params["created[gte]"] = inputs["created_gte"] if "created_lte" in inputs and inputs["created_lte"]: params["created[lte]"] = inputs["created_lte"] - if "current_period_start_gte" in inputs and inputs["current_period_start_gte"]: + if ( + "current_period_start_gte" in inputs + and inputs["current_period_start_gte"] + ): params["current_period_start[gte]"] = inputs["current_period_start_gte"] - if "current_period_start_lte" in inputs and inputs["current_period_start_lte"]: + if ( + "current_period_start_lte" in inputs + and inputs["current_period_start_lte"] + ): params["current_period_start[lte]"] = inputs["current_period_start_lte"] headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", + method="GET", + headers=headers, + params=params, ) subscriptions = response.get("data", []) return ActionResult( - data={"subscriptions": subscriptions, "has_more": response.get("has_more", False), "result": True}, + data={ + "subscriptions": subscriptions, + "has_more": response.get("has_more", False), + "result": True, + }, cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"subscriptions": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "subscriptions": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -996,13 +1229,20 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="GET", headers=headers + f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", + method="GET", + headers=headers, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"subscription": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"subscription": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("create_subscription") @@ -1024,7 +1264,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["payment_behavior"] = inputs["payment_behavior"] if "billing_cycle_anchor" in inputs and inputs["billing_cycle_anchor"]: body["billing_cycle_anchor"] = inputs["billing_cycle_anchor"] - if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: + if ( + "cancel_at_period_end" in inputs + and inputs["cancel_at_period_end"] is not None + ): body["cancel_at_period_end"] = inputs["cancel_at_period_end"] if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs["cancel_at"] @@ -1045,13 +1288,21 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="POST", headers=headers, data=form_data + f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", + method="POST", + headers=headers, + data=form_data, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"subscription": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"subscription": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("update_subscription") @@ -1070,7 +1321,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["default_payment_method"] = inputs["default_payment_method"] if "payment_behavior" in inputs and inputs["payment_behavior"]: body["payment_behavior"] = inputs["payment_behavior"] - if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: + if ( + "cancel_at_period_end" in inputs + and inputs["cancel_at_period_end"] is not None + ): body["cancel_at_period_end"] = inputs["cancel_at_period_end"] if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs["cancel_at"] @@ -1095,10 +1349,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"subscription": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"subscription": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("cancel_subscription") @@ -1143,10 +1402,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data if form_data else None, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"subscription": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"subscription": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) # ---- Payment Method Action Handlers ---- @@ -1170,19 +1434,32 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods", method="GET", headers=headers, params=params + f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods", + method="GET", + headers=headers, + params=params, ) payment_methods = response.get("data", []) return ActionResult( - data={"payment_methods": payment_methods, "has_more": response.get("has_more", False), "result": True}, + data={ + "payment_methods": payment_methods, + "has_more": response.get("has_more", False), + "result": True, + }, cost_usd=0.0, ) except Exception as e: return ActionResult( - data={"payment_methods": [], "has_more": False, "result": False, "error": str(e)}, cost_usd=0.0 + data={ + "payment_methods": [], + "has_more": False, + "result": False, + "error": str(e), + }, + cost_usd=0.0, ) @@ -1201,10 +1478,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"payment_method": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"payment_method": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("attach_payment_method") @@ -1226,10 +1508,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"payment_method": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"payment_method": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) @stripe.action("detach_payment_method") @@ -1247,7 +1534,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response, "result": True}, cost_usd=0.0 + ) except Exception as e: - return ActionResult(data={"payment_method": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionResult( + data={"payment_method": {}, "result": False, "error": str(e)}, + cost_usd=0.0, + ) From fc9d56253ab57a92a2b6c5f2a99289d1f47cf67c Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:27:56 +1200 Subject: [PATCH 04/18] fix(stripe): move ConnectedAccountHandler after helper definitions to avoid NameError --- stripe/stripe.py | 49 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index 342c2c50..92e04687 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -12,31 +12,6 @@ # Load integration from config.json stripe = Integration.load() - -@stripe.connected_account() -class StripeConnectedAccountHandler(ConnectedAccountHandler): - async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountInfo: - try: - response = await context.fetch( - f"{STRIPE_API_BASE_URL}/{API_VERSION}/account", - method="GET", - headers=get_common_headers(), - ) - data = response.data or {} - email = data.get("email") or data.get("business_profile", {}).get( - "support_email", "" - ) - name = ( - data.get("business_profile", {}).get("name") - or data.get("display_name") - or email - or "Stripe Account" - ) - return ConnectedAccountInfo(username=name, user_id=data.get("id")) - except Exception: - return ConnectedAccountInfo(username="Stripe Account") - - # Base URL for Stripe API STRIPE_API_BASE_URL = "https://api.stripe.com" API_VERSION = "v1" @@ -103,6 +78,30 @@ def build_list_params(inputs: Dict[str, Any]) -> Dict[str, Any]: return params +@stripe.connected_account() +class StripeConnectedAccountHandler(ConnectedAccountHandler): + async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountInfo: + try: + response = await context.fetch( + f"{STRIPE_API_BASE_URL}/{API_VERSION}/account", + method="GET", + headers=get_common_headers(), + ) + data = response.data or {} + email = data.get("email") or data.get("business_profile", {}).get( + "support_email", "" + ) + name = ( + data.get("business_profile", {}).get("name") + or data.get("display_name") + or email + or "Stripe Account" + ) + return ConnectedAccountInfo(username=name, user_id=data.get("id")) + except Exception: + return ConnectedAccountInfo(username="Stripe Account") + + # ---- Customer Action Handlers ---- From 4f4e283d5ef59564084d6a122bf3fdf65ad0163e Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:29:36 +1200 Subject: [PATCH 05/18] style(stripe): ruff format --- stripe/tests/context.py | 4 ++- stripe/tests/test_stripe.py | 66 ++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/stripe/tests/context.py b/stripe/tests/context.py index 4113f09b..abc99e76 100644 --- a/stripe/tests/context.py +++ b/stripe/tests/context.py @@ -10,7 +10,9 @@ # Import using importlib to avoid conflict with 'stripe' package import importlib.util -spec = importlib.util.spec_from_file_location("stripe_module", os.path.join(parent_dir, "stripe.py")) +spec = importlib.util.spec_from_file_location( + "stripe_module", os.path.join(parent_dir, "stripe.py") +) stripe_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(stripe_module) stripe_integration = stripe_module.stripe diff --git a/stripe/tests/test_stripe.py b/stripe/tests/test_stripe.py index 721bb0d8..f1e65bf7 100644 --- a/stripe/tests/test_stripe.py +++ b/stripe/tests/test_stripe.py @@ -28,7 +28,9 @@ async def test_list_customers(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("list_customers", {"limit": 5}, context) + result = await stripe_integration.execute_action( + "list_customers", {"limit": 5}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -80,7 +82,9 @@ async def test_get_customer(customer_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("get_customer", {"customer_id": customer_id}, context) + result = await stripe_integration.execute_action( + "get_customer", {"customer_id": customer_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -187,7 +191,9 @@ async def test_list_invoices(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("list_invoices", {"limit": 5, "status": "draft"}, context) + result = await stripe_integration.execute_action( + "list_invoices", {"limit": 5, "status": "draft"}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -203,7 +209,9 @@ async def test_get_invoice(invoice_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("get_invoice", {"invoice_id": invoice_id}, context) + result = await stripe_integration.execute_action( + "get_invoice", {"invoice_id": invoice_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -246,7 +254,9 @@ async def test_delete_invoice(invoice_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("delete_invoice", {"invoice_id": invoice_id}, context) + result = await stripe_integration.execute_action( + "delete_invoice", {"invoice_id": invoice_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -262,7 +272,9 @@ async def test_delete_customer(customer_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("delete_customer", {"customer_id": customer_id}, context) + result = await stripe_integration.execute_action( + "delete_customer", {"customer_id": customer_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -281,7 +293,9 @@ async def test_list_products(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("list_products", {"limit": 5, "active": True}, context) + result = await stripe_integration.execute_action( + "list_products", {"limit": 5, "active": True}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -328,7 +342,9 @@ async def test_get_product(product_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("get_product", {"product_id": product_id}, context) + result = await stripe_integration.execute_action( + "get_product", {"product_id": product_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -374,7 +390,9 @@ async def test_list_prices(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("list_prices", {"limit": 5, "active": True}, context) + result = await stripe_integration.execute_action( + "list_prices", {"limit": 5, "active": True}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -421,7 +439,9 @@ async def test_get_price(price_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("get_price", {"price_id": price_id}, context) + result = await stripe_integration.execute_action( + "get_price", {"price_id": price_id}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -440,7 +460,9 @@ async def test_update_price(price_id: str): async with ExecutionContext(auth=auth) as context: try: result = await stripe_integration.execute_action( - "update_price", {"price_id": price_id, "active": True, "metadata": {"updated": "true"}}, context + "update_price", + {"price_id": price_id, "active": True, "metadata": {"updated": "true"}}, + context, ) data = result.result.data @@ -461,7 +483,9 @@ async def test_list_subscriptions(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action("list_subscriptions", {"limit": 5}, context) + result = await stripe_integration.execute_action( + "list_subscriptions", {"limit": 5}, context + ) data = result.result.data print(f"Result: {data.get('result')}") @@ -529,7 +553,9 @@ async def test_update_subscription(subscription_id: str): async with ExecutionContext(auth=auth) as context: try: result = await stripe_integration.execute_action( - "update_subscription", {"subscription_id": subscription_id, "metadata": {"updated": "true"}}, context + "update_subscription", + {"subscription_id": subscription_id, "metadata": {"updated": "true"}}, + context, ) data = result.result.data @@ -549,7 +575,11 @@ async def test_cancel_subscription(subscription_id: str): try: result = await stripe_integration.execute_action( "cancel_subscription", - {"subscription_id": subscription_id, "invoice_now": False, "prorate": False}, + { + "subscription_id": subscription_id, + "invoice_now": False, + "prorate": False, + }, context, ) @@ -572,7 +602,9 @@ async def test_list_payment_methods(customer_id: str): async with ExecutionContext(auth=auth) as context: try: result = await stripe_integration.execute_action( - "list_payment_methods", {"customer": customer_id, "type": "card", "limit": 5}, context + "list_payment_methods", + {"customer": customer_id, "type": "card", "limit": 5}, + context, ) data = result.result.data @@ -715,7 +747,9 @@ async def run_quick_tests(): parser = argparse.ArgumentParser(description="Stripe Integration Tests") parser.add_argument("api_key", nargs="?", help="Stripe test API key") - parser.add_argument("--quick", action="store_true", help="Run quick read-only tests") + parser.add_argument( + "--quick", action="store_true", help="Run quick read-only tests" + ) args = parser.parse_args() if args.api_key: From 699880f1df3562ff01af50b043d09972edc3bb27 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:32:40 +1200 Subject: [PATCH 06/18] style(stripe): fix ruff formatting with correct line-length 120 config --- stripe/stripe.py | 187 +++++++++--------------------------- stripe/tests/context.py | 4 +- stripe/tests/test_stripe.py | 48 +++------ 3 files changed, 58 insertions(+), 181 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index 92e04687..39853b57 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -88,15 +88,8 @@ async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountI headers=get_common_headers(), ) data = response.data or {} - email = data.get("email") or data.get("business_profile", {}).get( - "support_email", "" - ) - name = ( - data.get("business_profile", {}).get("name") - or data.get("display_name") - or email - or "Stripe Account" - ) + email = data.get("email") or data.get("business_profile", {}).get("support_email", "") + name = data.get("business_profile", {}).get("name") or data.get("display_name") or email or "Stripe Account" return ConnectedAccountInfo(username=name, user_id=data.get("id")) except Exception: return ConnectedAccountInfo(username="Stripe Account") @@ -168,14 +161,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"customer": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("create_customer") @@ -210,14 +199,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"customer": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("update_customer") @@ -253,14 +238,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"customer": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("delete_customer") @@ -367,14 +348,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("create_invoice") @@ -409,14 +386,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("update_invoice") @@ -450,14 +423,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("delete_invoice") @@ -518,14 +487,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("send_invoice") @@ -543,14 +508,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("pay_invoice") @@ -575,14 +536,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("void_invoice") @@ -600,14 +557,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) # ---- Invoice Item Action Handlers ---- @@ -676,9 +629,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice_item": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -721,9 +672,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice_item": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -763,9 +712,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice_item": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -878,14 +825,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"product": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("create_product") @@ -924,14 +867,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"product": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("update_product") @@ -973,14 +912,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"product": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) # ---- Price Action Handlers ---- @@ -1058,9 +993,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("create_price") @@ -1111,9 +1044,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) @stripe.action("update_price") @@ -1148,9 +1079,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0 - ) + return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) # ---- Subscription Action Handlers ---- @@ -1175,15 +1104,9 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params["created[gte]"] = inputs["created_gte"] if "created_lte" in inputs and inputs["created_lte"]: params["created[lte]"] = inputs["created_lte"] - if ( - "current_period_start_gte" in inputs - and inputs["current_period_start_gte"] - ): + if "current_period_start_gte" in inputs and inputs["current_period_start_gte"]: params["current_period_start[gte]"] = inputs["current_period_start_gte"] - if ( - "current_period_start_lte" in inputs - and inputs["current_period_start_lte"] - ): + if "current_period_start_lte" in inputs and inputs["current_period_start_lte"]: params["current_period_start[lte]"] = inputs["current_period_start_lte"] headers = get_common_headers() @@ -1233,9 +1156,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"subscription": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1263,10 +1184,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["payment_behavior"] = inputs["payment_behavior"] if "billing_cycle_anchor" in inputs and inputs["billing_cycle_anchor"]: body["billing_cycle_anchor"] = inputs["billing_cycle_anchor"] - if ( - "cancel_at_period_end" in inputs - and inputs["cancel_at_period_end"] is not None - ): + if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: body["cancel_at_period_end"] = inputs["cancel_at_period_end"] if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs["cancel_at"] @@ -1293,9 +1211,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"subscription": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1320,10 +1236,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["default_payment_method"] = inputs["default_payment_method"] if "payment_behavior" in inputs and inputs["payment_behavior"]: body["payment_behavior"] = inputs["payment_behavior"] - if ( - "cancel_at_period_end" in inputs - and inputs["cancel_at_period_end"] is not None - ): + if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: body["cancel_at_period_end"] = inputs["cancel_at_period_end"] if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs["cancel_at"] @@ -1348,9 +1261,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"subscription": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1401,9 +1312,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data if form_data else None, ) - return ActionResult( - data={"subscription": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1477,9 +1386,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"payment_method": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1507,9 +1414,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"payment_method": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1533,9 +1438,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"payment_method": response, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( diff --git a/stripe/tests/context.py b/stripe/tests/context.py index abc99e76..4113f09b 100644 --- a/stripe/tests/context.py +++ b/stripe/tests/context.py @@ -10,9 +10,7 @@ # Import using importlib to avoid conflict with 'stripe' package import importlib.util -spec = importlib.util.spec_from_file_location( - "stripe_module", os.path.join(parent_dir, "stripe.py") -) +spec = importlib.util.spec_from_file_location("stripe_module", os.path.join(parent_dir, "stripe.py")) stripe_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(stripe_module) stripe_integration = stripe_module.stripe diff --git a/stripe/tests/test_stripe.py b/stripe/tests/test_stripe.py index f1e65bf7..3b2af146 100644 --- a/stripe/tests/test_stripe.py +++ b/stripe/tests/test_stripe.py @@ -28,9 +28,7 @@ async def test_list_customers(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "list_customers", {"limit": 5}, context - ) + result = await stripe_integration.execute_action("list_customers", {"limit": 5}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -82,9 +80,7 @@ async def test_get_customer(customer_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "get_customer", {"customer_id": customer_id}, context - ) + result = await stripe_integration.execute_action("get_customer", {"customer_id": customer_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -191,9 +187,7 @@ async def test_list_invoices(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "list_invoices", {"limit": 5, "status": "draft"}, context - ) + result = await stripe_integration.execute_action("list_invoices", {"limit": 5, "status": "draft"}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -209,9 +203,7 @@ async def test_get_invoice(invoice_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "get_invoice", {"invoice_id": invoice_id}, context - ) + result = await stripe_integration.execute_action("get_invoice", {"invoice_id": invoice_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -254,9 +246,7 @@ async def test_delete_invoice(invoice_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "delete_invoice", {"invoice_id": invoice_id}, context - ) + result = await stripe_integration.execute_action("delete_invoice", {"invoice_id": invoice_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -272,9 +262,7 @@ async def test_delete_customer(customer_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "delete_customer", {"customer_id": customer_id}, context - ) + result = await stripe_integration.execute_action("delete_customer", {"customer_id": customer_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -293,9 +281,7 @@ async def test_list_products(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "list_products", {"limit": 5, "active": True}, context - ) + result = await stripe_integration.execute_action("list_products", {"limit": 5, "active": True}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -342,9 +328,7 @@ async def test_get_product(product_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "get_product", {"product_id": product_id}, context - ) + result = await stripe_integration.execute_action("get_product", {"product_id": product_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -390,9 +374,7 @@ async def test_list_prices(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "list_prices", {"limit": 5, "active": True}, context - ) + result = await stripe_integration.execute_action("list_prices", {"limit": 5, "active": True}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -439,9 +421,7 @@ async def test_get_price(price_id: str): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "get_price", {"price_id": price_id}, context - ) + result = await stripe_integration.execute_action("get_price", {"price_id": price_id}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -483,9 +463,7 @@ async def test_list_subscriptions(): async with ExecutionContext(auth=auth) as context: try: - result = await stripe_integration.execute_action( - "list_subscriptions", {"limit": 5}, context - ) + result = await stripe_integration.execute_action("list_subscriptions", {"limit": 5}, context) data = result.result.data print(f"Result: {data.get('result')}") @@ -747,9 +725,7 @@ async def run_quick_tests(): parser = argparse.ArgumentParser(description="Stripe Integration Tests") parser.add_argument("api_key", nargs="?", help="Stripe test API key") - parser.add_argument( - "--quick", action="store_true", help="Run quick read-only tests" - ) + parser.add_argument("--quick", action="store_true", help="Run quick read-only tests") args = parser.parse_args() if args.api_key: From dcf653ff2c1199cb30771fc9026d6db898af5a38 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:13:11 +1200 Subject: [PATCH 07/18] fix(stripe): fix response.data access bug, rewrite tests as pytest unit + integration suite --- stripe/stripe.py | 92 +-- stripe/tests/conftest.py | 55 ++ stripe/tests/context.py | 16 - stripe/tests/test_stripe.py | 737 ------------------------ stripe/tests/test_stripe_integration.py | 145 +++++ stripe/tests/test_stripe_unit.py | 234 ++++++++ 6 files changed, 480 insertions(+), 799 deletions(-) create mode 100644 stripe/tests/conftest.py delete mode 100644 stripe/tests/context.py delete mode 100644 stripe/tests/test_stripe.py create mode 100644 stripe/tests/test_stripe_integration.py create mode 100644 stripe/tests/test_stripe_unit.py diff --git a/stripe/stripe.py b/stripe/stripe.py index 39853b57..bfd08a4a 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -123,12 +123,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - customers = response.get("data", []) + customers = response.data.get("data", []) return ActionResult( data={ "customers": customers, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -161,7 +161,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -199,7 +199,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -238,7 +238,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"customer": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -261,8 +261,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult( data={ - "id": response.get("id", customer_id), - "deleted": response.get("deleted", True), + "id": response.data.get("id", customer_id), + "deleted": response.data.get("deleted", True), "result": True, }, cost_usd=0.0, @@ -310,12 +310,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - invoices = response.get("data", []) + invoices = response.data.get("data", []) return ActionResult( data={ "invoices": invoices, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -348,7 +348,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -386,7 +386,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -423,7 +423,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -446,8 +446,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult( data={ - "id": response.get("id", invoice_id), - "deleted": response.get("deleted", True), + "id": response.data.get("id", invoice_id), + "deleted": response.data.get("deleted", True), "result": True, }, cost_usd=0.0, @@ -487,7 +487,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -508,7 +508,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -536,7 +536,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -557,7 +557,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"invoice": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -591,12 +591,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - invoice_items = response.get("data", []) + invoice_items = response.data.get("data", []) return ActionResult( data={ "invoice_items": invoice_items, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -629,7 +629,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -672,7 +672,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -712,7 +712,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"invoice_item": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -738,8 +738,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult( data={ - "id": response.get("id", invoice_item_id), - "deleted": response.get("deleted", True), + "id": response.data.get("id", invoice_item_id), + "deleted": response.data.get("deleted", True), "result": True, }, cost_usd=0.0, @@ -787,12 +787,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - products = response.get("data", []) + products = response.data.get("data", []) return ActionResult( data={ "products": products, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -825,7 +825,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -867,7 +867,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -912,7 +912,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"product": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -952,12 +952,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - prices = response.get("data", []) + prices = response.data.get("data", []) return ActionResult( data={ "prices": prices, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -990,7 +990,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -1041,7 +1041,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -1076,7 +1076,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"price": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) @@ -1118,12 +1118,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - subscriptions = response.get("data", []) + subscriptions = response.data.get("data", []) return ActionResult( data={ "subscriptions": subscriptions, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -1156,7 +1156,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1211,7 +1211,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1261,7 +1261,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1312,7 +1312,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data if form_data else None, ) - return ActionResult(data={"subscription": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1348,12 +1348,12 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params=params, ) - payment_methods = response.get("data", []) + payment_methods = response.data.get("data", []) return ActionResult( data={ "payment_methods": payment_methods, - "has_more": response.get("has_more", False), + "has_more": response.data.get("has_more", False), "result": True, }, cost_usd=0.0, @@ -1386,7 +1386,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1414,7 +1414,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( @@ -1438,7 +1438,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult(data={"payment_method": response, "result": True}, cost_usd=0.0) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionResult( diff --git a/stripe/tests/conftest.py b/stripe/tests/conftest.py new file mode 100644 index 00000000..b4f4bd70 --- /dev/null +++ b/stripe/tests/conftest.py @@ -0,0 +1,55 @@ +import os +import sys + +import pytest + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + + +def _get_env(var: str) -> str | None: + val = os.environ.get(var) + return val if val else None + + +@pytest.fixture +def mock_context(mocker): + from unittest.mock import AsyncMock, MagicMock + from autohive_integrations_sdk import FetchResponse + + ctx = MagicMock(name="ExecutionContext") + ctx.fetch = AsyncMock(return_value=FetchResponse(status=200, headers={}, data={})) + ctx.auth = { + "auth_type": "PlatformOauth2", + "credentials": {"access_token": "sk_test_fake"}, # nosec B105 + } + return ctx + + +@pytest.fixture +def stripe_context(): + import aiohttp + import json as _json + from unittest.mock import AsyncMock, MagicMock + from autohive_integrations_sdk import FetchResponse + + api_key = _get_env("STRIPE_TEST_API_KEY") + if not api_key: + pytest.skip("STRIPE_TEST_API_KEY not set — skipping integration tests") + + async def real_fetch(url, *, method="GET", json=None, headers=None, params=None, data=None, **kwargs): + merged = dict(headers or {}) + merged["Authorization"] = f"Bearer {api_key}" + + async with aiohttp.ClientSession() as session: + async with session.request(method, url, headers=merged, params=params, data=data, json=json) as resp: + text = await resp.text() + body = _json.loads(text) if text.strip() else {} + return FetchResponse(status=resp.status, headers=dict(resp.headers), data=body) + + ctx = MagicMock(name="ExecutionContext") + ctx.fetch = AsyncMock(side_effect=real_fetch) + ctx.auth = { + "auth_type": "PlatformOauth2", + "credentials": {"access_token": api_key}, + } + return ctx diff --git a/stripe/tests/context.py b/stripe/tests/context.py deleted file mode 100644 index 4113f09b..00000000 --- a/stripe/tests/context.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -import sys -import os - -# Add parent directory to path for imports -parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) -sys.path.insert(0, parent_dir) -sys.path.insert(0, os.path.join(parent_dir, "dependencies")) - -# Import using importlib to avoid conflict with 'stripe' package -import importlib.util - -spec = importlib.util.spec_from_file_location("stripe_module", os.path.join(parent_dir, "stripe.py")) -stripe_module = importlib.util.module_from_spec(spec) -spec.loader.exec_module(stripe_module) -stripe_integration = stripe_module.stripe diff --git a/stripe/tests/test_stripe.py b/stripe/tests/test_stripe.py deleted file mode 100644 index 3b2af146..00000000 --- a/stripe/tests/test_stripe.py +++ /dev/null @@ -1,737 +0,0 @@ -""" -Test suite for Stripe integration. - -These tests require a valid Stripe API key to run. -Set your test key before running: export STRIPE_TEST_API_KEY=sk_test_xxx - -Usage: - cd stripe/tests - python test_stripe.py sk_test_xxx # Full test suite - python test_stripe.py sk_test_xxx --quick # Read-only tests -""" - -import asyncio -import os - -from context import stripe_integration -from autohive_integrations_sdk import ExecutionContext - - -# Test API key - from environment or will be set via argparse -API_KEY = os.environ.get("STRIPE_TEST_API_KEY", "sk_test_your_key_here") - - -async def test_list_customers(): - """Test listing customers.""" - print("\n=== Test: List Customers ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("list_customers", {"limit": 5}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Customers found: {len(data.get('customers', []))}") - print(f"Has more: {data.get('has_more')}") - - if data.get("customers"): - customer = data["customers"][0] - print(f"First customer ID: {customer.get('id')}") - print(f"First customer email: {customer.get('email')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_create_customer(): - """Test creating a customer.""" - print("\n=== Test: Create Customer ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_customer", - { - "email": "test@example.com", - "name": "Test Customer", - "description": "Created by integration test", - "metadata": {"test": "true"}, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - customer = data.get("customer", {}) - print(f"Customer ID: {customer.get('id')}") - print(f"Customer email: {customer.get('email')}") - - return customer.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_get_customer(customer_id: str): - """Test getting a specific customer.""" - print("\n=== Test: Get Customer ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("get_customer", {"customer_id": customer_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - customer = data.get("customer", {}) - print(f"Customer ID: {customer.get('id')}") - print(f"Customer name: {customer.get('name')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_update_customer(customer_id: str): - """Test updating a customer.""" - print("\n=== Test: Update Customer ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "update_customer", - { - "customer_id": customer_id, - "name": "Updated Test Customer", - "description": "Updated by integration test", - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - customer = data.get("customer", {}) - print(f"Updated name: {customer.get('name')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_create_invoice(customer_id: str): - """Test creating a draft invoice.""" - print("\n=== Test: Create Invoice ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_invoice", - { - "customer": customer_id, - "currency": "nzd", - "description": "Test Invoice - RUC Purchase", - "auto_advance": False, - "collection_method": "send_invoice", - "days_until_due": 30, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - invoice = data.get("invoice", {}) - print(f"Invoice ID: {invoice.get('id')}") - print(f"Invoice status: {invoice.get('status')}") - - return invoice.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_create_invoice_item(customer_id: str, invoice_id: str): - """Test creating an invoice item.""" - print("\n=== Test: Create Invoice Item ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_invoice_item", - { - "customer": customer_id, - "invoice": invoice_id, - "unit_amount": 6609, # $66.09 in cents - "currency": "nzd", - "quantity": 5, - "description": "RUC - 5 units (5,000km)", - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - item = data.get("invoice_item", {}) - print(f"Invoice Item ID: {item.get('id')}") - print(f"Amount: {item.get('amount')}") - - return item.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_list_invoices(): - """Test listing invoices.""" - print("\n=== Test: List Invoices ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("list_invoices", {"limit": 5, "status": "draft"}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Invoices found: {len(data.get('invoices', []))}") - except Exception as e: - print(f"Error: {e}") - - -async def test_get_invoice(invoice_id: str): - """Test getting a specific invoice.""" - print("\n=== Test: Get Invoice ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("get_invoice", {"invoice_id": invoice_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - invoice = data.get("invoice", {}) - print(f"Invoice ID: {invoice.get('id')}") - print(f"Invoice total: {invoice.get('total')}") - print(f"Invoice status: {invoice.get('status')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_update_invoice(invoice_id: str): - """Test updating an invoice.""" - print("\n=== Test: Update Invoice ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "update_invoice", - { - "invoice_id": invoice_id, - "description": "Updated: RUC Purchase - GTR680 (Test Vehicle)\n5 units (5,000km)", - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - invoice = data.get("invoice", {}) - print(f"Updated description: {invoice.get('description')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_delete_invoice(invoice_id: str): - """Test deleting a draft invoice.""" - print("\n=== Test: Delete Invoice ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("delete_invoice", {"invoice_id": invoice_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Deleted: {data.get('deleted')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_delete_customer(customer_id: str): - """Test deleting a customer.""" - print("\n=== Test: Delete Customer ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("delete_customer", {"customer_id": customer_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Deleted: {data.get('deleted')}") - except Exception as e: - print(f"Error: {e}") - - -# ---- Product Tests ---- - - -async def test_list_products(): - """Test listing products.""" - print("\n=== Test: List Products ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("list_products", {"limit": 5, "active": True}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Products found: {len(data.get('products', []))}") - print(f"Has more: {data.get('has_more')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_create_product(): - """Test creating a product.""" - print("\n=== Test: Create Product ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_product", - { - "name": "Test Product", - "description": "Created by integration test", - "active": True, - "metadata": {"test": "true"}, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - product = data.get("product", {}) - print(f"Product ID: {product.get('id')}") - print(f"Product name: {product.get('name')}") - - return product.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_get_product(product_id: str): - """Test getting a specific product.""" - print("\n=== Test: Get Product ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("get_product", {"product_id": product_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - product = data.get("product", {}) - print(f"Product ID: {product.get('id')}") - print(f"Product name: {product.get('name')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_update_product(product_id: str): - """Test updating a product.""" - print("\n=== Test: Update Product ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "update_product", - { - "product_id": product_id, - "name": "Updated Test Product", - "description": "Updated by integration test", - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - product = data.get("product", {}) - print(f"Updated name: {product.get('name')}") - except Exception as e: - print(f"Error: {e}") - - -# ---- Price Tests ---- - - -async def test_list_prices(): - """Test listing prices.""" - print("\n=== Test: List Prices ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("list_prices", {"limit": 5, "active": True}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Prices found: {len(data.get('prices', []))}") - print(f"Has more: {data.get('has_more')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_create_price(product_id: str): - """Test creating a price for a product.""" - print("\n=== Test: Create Price ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_price", - { - "product": product_id, - "currency": "usd", - "unit_amount": 1999, # $19.99 - "recurring": {"interval": "month", "interval_count": 1}, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - price = data.get("price", {}) - print(f"Price ID: {price.get('id')}") - print(f"Unit amount: {price.get('unit_amount')}") - - return price.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_get_price(price_id: str): - """Test getting a specific price.""" - print("\n=== Test: Get Price ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("get_price", {"price_id": price_id}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - price = data.get("price", {}) - print(f"Price ID: {price.get('id')}") - print(f"Unit amount: {price.get('unit_amount')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_update_price(price_id: str): - """Test updating a price.""" - print("\n=== Test: Update Price ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "update_price", - {"price_id": price_id, "active": True, "metadata": {"updated": "true"}}, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - price = data.get("price", {}) - print(f"Price active: {price.get('active')}") - except Exception as e: - print(f"Error: {e}") - - -# ---- Subscription Tests ---- - - -async def test_list_subscriptions(): - """Test listing subscriptions.""" - print("\n=== Test: List Subscriptions ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action("list_subscriptions", {"limit": 5}, context) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Subscriptions found: {len(data.get('subscriptions', []))}") - print(f"Has more: {data.get('has_more')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_create_subscription(customer_id: str, price_id: str): - """Test creating a subscription.""" - print("\n=== Test: Create Subscription ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "create_subscription", - { - "customer": customer_id, - "items": [{"price": price_id}], - "payment_behavior": "default_incomplete", - "metadata": {"test": "true"}, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - subscription = data.get("subscription", {}) - print(f"Subscription ID: {subscription.get('id')}") - print(f"Subscription status: {subscription.get('status')}") - - return subscription.get("id") - except Exception as e: - print(f"Error: {e}") - return None - - -async def test_get_subscription(subscription_id: str): - """Test getting a specific subscription.""" - print("\n=== Test: Get Subscription ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "get_subscription", {"subscription_id": subscription_id}, context - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - subscription = data.get("subscription", {}) - print(f"Subscription ID: {subscription.get('id')}") - print(f"Subscription status: {subscription.get('status')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_update_subscription(subscription_id: str): - """Test updating a subscription.""" - print("\n=== Test: Update Subscription ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "update_subscription", - {"subscription_id": subscription_id, "metadata": {"updated": "true"}}, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - subscription = data.get("subscription", {}) - print(f"Subscription ID: {subscription.get('id')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_cancel_subscription(subscription_id: str): - """Test canceling a subscription.""" - print("\n=== Test: Cancel Subscription ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "cancel_subscription", - { - "subscription_id": subscription_id, - "invoice_now": False, - "prorate": False, - }, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - subscription = data.get("subscription", {}) - print(f"Subscription status: {subscription.get('status')}") - except Exception as e: - print(f"Error: {e}") - - -# ---- Payment Method Tests ---- - - -async def test_list_payment_methods(customer_id: str): - """Test listing payment methods for a customer.""" - print("\n=== Test: List Payment Methods ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "list_payment_methods", - {"customer": customer_id, "type": "card", "limit": 5}, - context, - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - print(f"Payment methods found: {len(data.get('payment_methods', []))}") - print(f"Has more: {data.get('has_more')}") - except Exception as e: - print(f"Error: {e}") - - -async def test_get_payment_method(payment_method_id: str): - """Test getting a specific payment method.""" - print("\n=== Test: Get Payment Method ===") - auth = {"credentials": {"api_key": API_KEY}} - - async with ExecutionContext(auth=auth) as context: - try: - result = await stripe_integration.execute_action( - "get_payment_method", {"payment_method_id": payment_method_id}, context - ) - - data = result.result.data - print(f"Result: {data.get('result')}") - pm = data.get("payment_method", {}) - print(f"Payment Method ID: {pm.get('id')}") - print(f"Type: {pm.get('type')}") - except Exception as e: - print(f"Error: {e}") - - -async def run_all_tests(): - """Run all tests in sequence.""" - print("=" * 60) - print("STRIPE INTEGRATION TEST SUITE") - print("=" * 60) - - if API_KEY == "sk_test_your_key_here": - print("\nWARNING: Using placeholder API key. Tests will fail.") - print("Set STRIPE_TEST_API_KEY environment variable with your test key.") - print("=" * 60) - - # Test customer CRUD - print("\n" + "-" * 40) - print("CUSTOMER TESTS") - print("-" * 40) - await test_list_customers() - - customer_id = await test_create_customer() - if customer_id: - await test_get_customer(customer_id) - await test_update_customer(customer_id) - - # Test invoice CRUD - print("\n" + "-" * 40) - print("INVOICE TESTS") - print("-" * 40) - invoice_id = await test_create_invoice(customer_id) - if invoice_id: - await test_create_invoice_item(customer_id, invoice_id) - await test_get_invoice(invoice_id) - await test_update_invoice(invoice_id) - await test_list_invoices() - - # Clean up - delete invoice - await test_delete_invoice(invoice_id) - - # Test product CRUD - print("\n" + "-" * 40) - print("PRODUCT TESTS") - print("-" * 40) - await test_list_products() - product_id = await test_create_product() - if product_id: - await test_get_product(product_id) - await test_update_product(product_id) - - # Test price CRUD (requires product) - print("\n" + "-" * 40) - print("PRICE TESTS") - print("-" * 40) - await test_list_prices() - price_id = await test_create_price(product_id) - if price_id: - await test_get_price(price_id) - await test_update_price(price_id) - - # Test subscription CRUD (requires customer and price) - print("\n" + "-" * 40) - print("SUBSCRIPTION TESTS") - print("-" * 40) - await test_list_subscriptions() - subscription_id = await test_create_subscription(customer_id, price_id) - if subscription_id: - await test_get_subscription(subscription_id) - await test_update_subscription(subscription_id) - # Clean up - cancel subscription - await test_cancel_subscription(subscription_id) - - # Test payment method operations - print("\n" + "-" * 40) - print("PAYMENT METHOD TESTS") - print("-" * 40) - await test_list_payment_methods(customer_id) - - # Clean up - delete customer - print("\n" + "-" * 40) - print("CLEANUP") - print("-" * 40) - await test_delete_customer(customer_id) - - print("\n" + "=" * 60) - print("TEST SUITE COMPLETE") - print("=" * 60) - - -async def run_quick_tests(): - """Run quick read-only tests (no create/update/delete).""" - print("=" * 60) - print("STRIPE INTEGRATION QUICK TEST (READ-ONLY)") - print("=" * 60) - - if API_KEY == "sk_test_your_key_here": - print("\nWARNING: Using placeholder API key. Tests will fail.") - print("Set STRIPE_TEST_API_KEY environment variable with your test key.") - print("=" * 60) - - await test_list_customers() - await test_list_invoices() - await test_list_products() - await test_list_prices() - await test_list_subscriptions() - - print("\n" + "=" * 60) - print("QUICK TEST COMPLETE") - print("=" * 60) - - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser(description="Stripe Integration Tests") - parser.add_argument("api_key", nargs="?", help="Stripe test API key") - parser.add_argument("--quick", action="store_true", help="Run quick read-only tests") - args = parser.parse_args() - - if args.api_key: - API_KEY = args.api_key - - if args.quick: - asyncio.run(run_quick_tests()) - else: - asyncio.run(run_all_tests()) diff --git a/stripe/tests/test_stripe_integration.py b/stripe/tests/test_stripe_integration.py new file mode 100644 index 00000000..5ac66316 --- /dev/null +++ b/stripe/tests/test_stripe_integration.py @@ -0,0 +1,145 @@ +""" +Live integration tests for the Stripe integration. + +Requires STRIPE_TEST_API_KEY set in the environment (use a test-mode key: sk_test_...). + +Run with: + pytest stripe/tests/test_stripe_integration.py -m "integration" -o "addopts=--import-mode=importlib --tb=short" +""" + +import time + +import pytest +from autohive_integrations_sdk.integration import ResultType + +from stripe.stripe import stripe + +pytestmark = pytest.mark.integration + + +# ---- Read-Only Tests ---- + + +class TestListCustomers: + async def test_returns_list(self, stripe_context): + result = await stripe.execute_action("list_customers", {"limit": 5}, stripe_context) + assert result.type == ResultType.ACTION + data = result.result.data + assert data["result"] is True + assert "customers" in data + assert isinstance(data["customers"], list) + + +class TestListInvoices: + async def test_returns_list(self, stripe_context): + result = await stripe.execute_action("list_invoices", {"limit": 5}, stripe_context) + assert result.type == ResultType.ACTION + data = result.result.data + assert data["result"] is True + assert "invoices" in data + + +class TestListProducts: + async def test_returns_list(self, stripe_context): + result = await stripe.execute_action("list_products", {"limit": 5}, stripe_context) + assert result.type == ResultType.ACTION + data = result.result.data + assert data["result"] is True + assert "products" in data + + async def test_active_filter(self, stripe_context): + result = await stripe.execute_action("list_products", {"limit": 5, "active": True}, stripe_context) + data = result.result.data + assert data["result"] is True + for p in data["products"]: + assert p.get("active") is True + + +class TestListPrices: + async def test_returns_list(self, stripe_context): + result = await stripe.execute_action("list_prices", {"limit": 5}, stripe_context) + assert result.type == ResultType.ACTION + data = result.result.data + assert data["result"] is True + assert "prices" in data + + +class TestListSubscriptions: + async def test_returns_list(self, stripe_context): + result = await stripe.execute_action("list_subscriptions", {"limit": 5}, stripe_context) + assert result.type == ResultType.ACTION + data = result.result.data + assert data["result"] is True + assert "subscriptions" in data + + +# ---- Destructive Tests ---- + + +@pytest.mark.destructive +class TestCustomerLifecycle: + """Create → get → update → delete a test customer.""" + + async def test_full_lifecycle(self, stripe_context): + uid = int(time.time()) + + # Create + create = await stripe.execute_action( + "create_customer", + {"email": f"ah-test-{uid}@example.com", "name": f"AH Test {uid}"}, + stripe_context, + ) + assert create.result.data["result"] is True + customer_id = create.result.data["customer"]["id"] + assert customer_id.startswith("cus_") + + # Get + get = await stripe.execute_action("get_customer", {"customer_id": customer_id}, stripe_context) + assert get.result.data["customer"]["id"] == customer_id + + # Update + update = await stripe.execute_action( + "update_customer", + {"customer_id": customer_id, "name": f"AH Updated {uid}"}, + stripe_context, + ) + assert update.result.data["result"] is True + + # Delete (cleanup) + delete = await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + assert delete.result.data["result"] is True + assert delete.result.data["deleted"] is True + + +@pytest.mark.destructive +class TestProductAndPriceLifecycle: + """Create product → create price → get each → cleanup.""" + + async def test_full_lifecycle(self, stripe_context): + uid = int(time.time()) + + # Create product + prod = await stripe.execute_action( + "create_product", + {"name": f"AH Test Product {uid}", "active": True}, + stripe_context, + ) + assert prod.result.data["result"] is True + product_id = prod.result.data["product"]["id"] + + # Create price + price = await stripe.execute_action( + "create_price", + {"product": product_id, "currency": "usd", "unit_amount": 999}, + stripe_context, + ) + assert price.result.data["result"] is True + price_id = price.result.data["price"]["id"] + + # Get price + get_price = await stripe.execute_action("get_price", {"price_id": price_id}, stripe_context) + assert get_price.result.data["price"]["id"] == price_id + + # Get product + get_prod = await stripe.execute_action("get_product", {"product_id": product_id}, stripe_context) + assert get_prod.result.data["product"]["id"] == product_id diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py new file mode 100644 index 00000000..784dd242 --- /dev/null +++ b/stripe/tests/test_stripe_unit.py @@ -0,0 +1,234 @@ +import pytest +from unittest.mock import AsyncMock, MagicMock +from autohive_integrations_sdk import FetchResponse +from autohive_integrations_sdk.integration import ResultType + +from stripe.stripe import stripe + +pytestmark = pytest.mark.unit + +SAMPLE_CUSTOMER = { + "id": "cus_test123", + "object": "customer", + "email": "test@example.com", + "name": "Test Customer", +} + +SAMPLE_INVOICE = { + "id": "in_test123", + "object": "invoice", + "customer": "cus_test123", + "status": "draft", + "total": 5000, +} + +SAMPLE_PRODUCT = { + "id": "prod_test123", + "object": "product", + "name": "Test Product", + "active": True, +} + +SAMPLE_PRICE = { + "id": "price_test123", + "object": "price", + "product": "prod_test123", + "unit_amount": 1999, + "currency": "usd", +} + +SAMPLE_SUBSCRIPTION = { + "id": "sub_test123", + "object": "subscription", + "customer": "cus_test123", + "status": "active", +} + +SAMPLE_LIST = { + "object": "list", + "data": [], + "has_more": False, +} + + +@pytest.fixture +def ctx(): + mock = MagicMock(name="ExecutionContext") + mock.fetch = AsyncMock(return_value=FetchResponse(status=200, headers={}, data={})) + mock.auth = {"auth_type": "PlatformOauth2", "credentials": {"access_token": "sk_test_fake"}} # nosec B105 + return mock + + +# ---- Customers ---- + + +class TestListCustomers: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_CUSTOMER]}) + result = await stripe.execute_action("list_customers", {"limit": 5}, ctx) + assert result.type == ResultType.ACTION + assert result.result.data["result"] is True + assert len(result.result.data["customers"]) == 1 + + async def test_url_and_method(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) + await stripe.execute_action("list_customers", {}, ctx) + call = ctx.fetch.call_args + assert "customers" in call.args[0] + assert call.kwargs["method"] == "GET" + + async def test_exception_returns_result_false(self, ctx): + ctx.fetch.side_effect = Exception("timeout") + result = await stripe.execute_action("list_customers", {}, ctx) + assert result.result.data["result"] is False + assert "timeout" in result.result.data["error"] + + +class TestGetCustomer: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) + result = await stripe.execute_action("get_customer", {"customer_id": "cus_test123"}, ctx) + assert result.type == ResultType.ACTION + assert result.result.data["result"] is True + assert result.result.data["customer"]["id"] == "cus_test123" + + async def test_url_contains_customer_id(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) + await stripe.execute_action("get_customer", {"customer_id": "cus_abc"}, ctx) + assert "cus_abc" in ctx.fetch.call_args.args[0] + + +class TestCreateCustomer: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) + result = await stripe.execute_action( + "create_customer", + {"email": "test@example.com", "name": "Test"}, + ctx, + ) + assert result.result.data["result"] is True + assert "customer" in result.result.data + + async def test_uses_post(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) + await stripe.execute_action("create_customer", {"email": "x@x.com"}, ctx) + assert ctx.fetch.call_args.kwargs["method"] == "POST" + + +class TestDeleteCustomer: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "cus_test123", "deleted": True}) + result = await stripe.execute_action("delete_customer", {"customer_id": "cus_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["deleted"] is True + + +# ---- Invoices ---- + + +class TestListInvoices: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_INVOICE]}) + result = await stripe.execute_action("list_invoices", {"limit": 5}, ctx) + assert result.result.data["result"] is True + assert len(result.result.data["invoices"]) == 1 + + async def test_status_filter(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) + await stripe.execute_action("list_invoices", {"status": "draft"}, ctx) + params = ctx.fetch.call_args.kwargs.get("params", {}) + assert params.get("status") == "draft" + + +class TestGetInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) + result = await stripe.execute_action("get_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["invoice"]["id"] == "in_test123" + + +class TestDeleteInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "in_test123", "deleted": True}) + result = await stripe.execute_action("delete_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["deleted"] is True + + +# ---- Products ---- + + +class TestListProducts: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRODUCT]}) + result = await stripe.execute_action("list_products", {"limit": 3}, ctx) + assert result.result.data["result"] is True + assert len(result.result.data["products"]) == 1 + + async def test_active_filter(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) + await stripe.execute_action("list_products", {"active": True}, ctx) + params = ctx.fetch.call_args.kwargs.get("params", {}) + assert params.get("active") == "true" + + +class TestGetProduct: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRODUCT) + result = await stripe.execute_action("get_product", {"product_id": "prod_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["product"]["id"] == "prod_test123" + + +# ---- Prices ---- + + +class TestListPrices: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRICE]}) + result = await stripe.execute_action("list_prices", {"limit": 3}, ctx) + assert result.result.data["result"] is True + assert len(result.result.data["prices"]) == 1 + + +class TestGetPrice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRICE) + result = await stripe.execute_action("get_price", {"price_id": "price_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["price"]["id"] == "price_test123" + + +# ---- Subscriptions ---- + + +class TestListSubscriptions: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_SUBSCRIPTION]}) + result = await stripe.execute_action("list_subscriptions", {"limit": 3}, ctx) + assert result.result.data["result"] is True + assert len(result.result.data["subscriptions"]) == 1 + + +class TestGetSubscription: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) + result = await stripe.execute_action("get_subscription", {"subscription_id": "sub_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["subscription"]["id"] == "sub_test123" + + +# ---- Payment Methods ---- + + +class TestListPaymentMethods: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": []}) + result = await stripe.execute_action( + "list_payment_methods", + {"customer": "cus_test123", "type": "card"}, + ctx, + ) + assert result.result.data["result"] is True + assert "payment_methods" in result.result.data From 4888d64627c3145d2421289c248812f69cdb0bf3 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:18:55 +1200 Subject: [PATCH 08/18] test(stripe): expand to 44 unit + 10 integration tests covering all 36 actions; fix unit_amount_decimal mapping --- stripe/stripe.py | 6 +- stripe/tests/test_stripe_integration.py | 135 ++++++++++++++++ stripe/tests/test_stripe_unit.py | 205 ++++++++++++++++++++++++ 3 files changed, 343 insertions(+), 3 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index bfd08a4a..aaf891f0 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -658,7 +658,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs["quantity"] if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount_decimal"] = inputs["unit_amount"] + body["unit_amount_decimal"] = str(inputs["unit_amount"]) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs["metadata"] @@ -698,7 +698,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs["quantity"] if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount_decimal"] = inputs["unit_amount"] + body["unit_amount_decimal"] = str(inputs["unit_amount"]) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs["metadata"] @@ -1009,7 +1009,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add unit_amount or custom_unit_amount if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount"] = inputs["unit_amount"] + body["unit_amount_decimal"] = str(inputs["unit_amount"]) elif "unit_amount_decimal" in inputs and inputs["unit_amount_decimal"]: body["unit_amount_decimal"] = inputs["unit_amount_decimal"] diff --git a/stripe/tests/test_stripe_integration.py b/stripe/tests/test_stripe_integration.py index 5ac66316..40a412af 100644 --- a/stripe/tests/test_stripe_integration.py +++ b/stripe/tests/test_stripe_integration.py @@ -143,3 +143,138 @@ async def test_full_lifecycle(self, stripe_context): # Get product get_prod = await stripe.execute_action("get_product", {"product_id": product_id}, stripe_context) assert get_prod.result.data["product"]["id"] == product_id + + +@pytest.mark.destructive +class TestInvoiceLifecycle: + """Create customer → create invoice → add item → finalize → void (cleanup).""" + + async def test_full_lifecycle(self, stripe_context): + uid = int(time.time()) + + # Create customer + cust = await stripe.execute_action( + "create_customer", + {"email": f"ah-inv-{uid}@example.com", "name": f"AH Invoice Test {uid}"}, + stripe_context, + ) + assert cust.result.data["result"] is True + customer_id = cust.result.data["customer"]["id"] + + # Create draft invoice + inv = await stripe.execute_action( + "create_invoice", + {"customer": customer_id, "collection_method": "send_invoice", "days_until_due": 30, "currency": "nzd"}, + stripe_context, + ) + assert inv.result.data["result"] is True + invoice_id = inv.result.data["invoice"]["id"] + assert inv.result.data["invoice"]["status"] == "draft" + + # Add invoice item + item = await stripe.execute_action( + "create_invoice_item", + {"customer": customer_id, "invoice": invoice_id, "unit_amount": 1000, "currency": "nzd"}, + stripe_context, + ) + assert item.result.data["result"] is True + item_id = item.result.data["invoice_item"]["id"] + + # Get invoice item + get_item = await stripe.execute_action("get_invoice_item", {"invoice_item_id": item_id}, stripe_context) + assert get_item.result.data["invoice_item"]["id"] == item_id + + # List invoice items + list_items = await stripe.execute_action("list_invoice_items", {"invoice": invoice_id}, stripe_context) + assert list_items.result.data["result"] is True + + # Get invoice + get_inv = await stripe.execute_action("get_invoice", {"invoice_id": invoice_id}, stripe_context) + assert get_inv.result.data["invoice"]["id"] == invoice_id + + # Update invoice + upd_inv = await stripe.execute_action( + "update_invoice", + {"invoice_id": invoice_id, "description": f"AH Test Invoice {uid}"}, + stripe_context, + ) + assert upd_inv.result.data["result"] is True + + # Finalize invoice + fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) + assert fin.result.data["result"] is True + assert fin.result.data["invoice"]["status"] == "open" + + # Void (cleanup) + void = await stripe.execute_action("void_invoice", {"invoice_id": invoice_id}, stripe_context) + assert void.result.data["result"] is True + assert void.result.data["invoice"]["status"] == "void" + + # Cleanup customer + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + + +@pytest.mark.destructive +class TestSubscriptionLifecycle: + """Create product + price → create customer → create subscription → update → cancel.""" + + async def test_full_lifecycle(self, stripe_context): + uid = int(time.time()) + + # Create product + price + prod = await stripe.execute_action("create_product", {"name": f"AH Sub Product {uid}"}, stripe_context) + product_id = prod.result.data["product"]["id"] + + price = await stripe.execute_action( + "create_price", + {"product": product_id, "currency": "usd", "unit_amount": 500, "recurring": {"interval": "month"}}, + stripe_context, + ) + price_id = price.result.data["price"]["id"] + + # Create customer + cust = await stripe.execute_action( + "create_customer", + {"email": f"ah-sub-{uid}@example.com"}, + stripe_context, + ) + customer_id = cust.result.data["customer"]["id"] + + # Create subscription + sub = await stripe.execute_action( + "create_subscription", + { + "customer": customer_id, + "items": [{"price": price_id}], + "payment_behavior": "default_incomplete", + "collection_method": "send_invoice", + "days_until_due": 30, + }, + stripe_context, + ) + assert sub.result.data["result"] is True + subscription_id = sub.result.data["subscription"]["id"] + + # Get subscription + get_sub = await stripe.execute_action("get_subscription", {"subscription_id": subscription_id}, stripe_context) + assert get_sub.result.data["subscription"]["id"] == subscription_id + + # Update subscription + upd = await stripe.execute_action( + "update_subscription", + {"subscription_id": subscription_id, "metadata": {"test": "true"}}, + stripe_context, + ) + assert upd.result.data["result"] is True + + # Cancel subscription (cleanup) + cancel = await stripe.execute_action( + "cancel_subscription", + {"subscription_id": subscription_id, "invoice_now": False, "prorate": False}, + stripe_context, + ) + assert cancel.result.data["result"] is True + assert cancel.result.data["subscription"]["status"] in ("canceled", "incomplete_expired") + + # Cleanup customer + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index 784dd242..a0d3b2e6 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -200,6 +200,114 @@ async def test_success(self, ctx): assert result.result.data["price"]["id"] == "price_test123" +# ---- Invoice Items ---- + + +class TestListInvoiceItems: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": []}) + result = await stripe.execute_action("list_invoice_items", {}, ctx) + assert result.result.data["result"] is True + assert "invoice_items" in result.result.data + + async def test_invoice_filter(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) + await stripe.execute_action("list_invoice_items", {"invoice": "in_test123"}, ctx) + params = ctx.fetch.call_args.kwargs.get("params", {}) + assert params.get("invoice") == "in_test123" + + +class TestGetInvoiceItem: + async def test_success(self, ctx): + item = {"id": "ii_test123", "object": "invoiceitem", "amount": 500} + ctx.fetch.return_value = FetchResponse(200, {}, item) + result = await stripe.execute_action("get_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["invoice_item"]["id"] == "ii_test123" + + +class TestCreateInvoiceItem: + async def test_success(self, ctx): + item = {"id": "ii_test123", "object": "invoiceitem", "amount": 500} + ctx.fetch.return_value = FetchResponse(200, {}, item) + result = await stripe.execute_action( + "create_invoice_item", + {"customer": "cus_test123", "unit_amount": 500, "currency": "usd"}, + ctx, + ) + assert result.result.data["result"] is True + + async def test_uses_post(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {}) + await stripe.execute_action( + "create_invoice_item", + {"customer": "cus_test123", "unit_amount": 500, "currency": "usd"}, + ctx, + ) + assert ctx.fetch.call_args.kwargs["method"] == "POST" + + +class TestDeleteInvoiceItem: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "ii_test123", "deleted": True}) + result = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["deleted"] is True + + +# ---- Invoice Lifecycle ---- + + +class TestFinalizeInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) + result = await stripe.execute_action("finalize_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["invoice"]["status"] == "open" + + async def test_url_contains_finalize(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) + await stripe.execute_action("finalize_invoice", {"invoice_id": "in_abc"}, ctx) + assert "finalize" in ctx.fetch.call_args.args[0] + assert "in_abc" in ctx.fetch.call_args.args[0] + + +class TestVoidInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "void"}) + result = await stripe.execute_action("void_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + + async def test_url_contains_void(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) + await stripe.execute_action("void_invoice", {"invoice_id": "in_abc"}, ctx) + assert "void" in ctx.fetch.call_args.args[0] + + +class TestSendInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) + result = await stripe.execute_action("send_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + + async def test_url_contains_send(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) + await stripe.execute_action("send_invoice", {"invoice_id": "in_abc"}, ctx) + assert "send" in ctx.fetch.call_args.args[0] + + +class TestPayInvoice: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "paid"}) + result = await stripe.execute_action("pay_invoice", {"invoice_id": "in_test123"}, ctx) + assert result.result.data["result"] is True + + async def test_url_contains_pay(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) + await stripe.execute_action("pay_invoice", {"invoice_id": "in_abc"}, ctx) + assert "/pay" in ctx.fetch.call_args.args[0] + + # ---- Subscriptions ---- @@ -219,6 +327,59 @@ async def test_success(self, ctx): assert result.result.data["subscription"]["id"] == "sub_test123" +class TestCreateSubscription: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) + result = await stripe.execute_action( + "create_subscription", + {"customer": "cus_test123", "items": [{"price": "price_test123"}]}, + ctx, + ) + assert result.result.data["result"] is True + assert "subscription" in result.result.data + + async def test_uses_post(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) + await stripe.execute_action( + "create_subscription", + {"customer": "cus_test123", "items": [{"price": "price_test123"}]}, + ctx, + ) + assert ctx.fetch.call_args.kwargs["method"] == "POST" + + +class TestUpdateSubscription: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) + result = await stripe.execute_action( + "update_subscription", + {"subscription_id": "sub_test123", "metadata": {"key": "val"}}, + ctx, + ) + assert result.result.data["result"] is True + + async def test_url_contains_subscription_id(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) + await stripe.execute_action( + "update_subscription", + {"subscription_id": "sub_abc"}, + ctx, + ) + assert "sub_abc" in ctx.fetch.call_args.args[0] + + +class TestCancelSubscription: + async def test_success(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_SUBSCRIPTION, "status": "canceled"}) + result = await stripe.execute_action( + "cancel_subscription", + {"subscription_id": "sub_test123"}, + ctx, + ) + assert result.result.data["result"] is True + assert result.result.data["subscription"]["status"] == "canceled" + + # ---- Payment Methods ---- @@ -232,3 +393,47 @@ async def test_success(self, ctx): ) assert result.result.data["result"] is True assert "payment_methods" in result.result.data + + +class TestGetPaymentMethod: + async def test_success(self, ctx): + pm = {"id": "pm_test123", "object": "payment_method", "type": "card"} + ctx.fetch.return_value = FetchResponse(200, {}, pm) + result = await stripe.execute_action("get_payment_method", {"payment_method_id": "pm_test123"}, ctx) + assert result.result.data["result"] is True + assert result.result.data["payment_method"]["id"] == "pm_test123" + + +class TestAttachPaymentMethod: + async def test_success(self, ctx): + pm = {"id": "pm_test123", "object": "payment_method", "customer": "cus_test123"} + ctx.fetch.return_value = FetchResponse(200, {}, pm) + result = await stripe.execute_action( + "attach_payment_method", + {"payment_method_id": "pm_test123", "customer": "cus_test123"}, + ctx, + ) + assert result.result.data["result"] is True + + async def test_url_contains_attach(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {}) + await stripe.execute_action( + "attach_payment_method", + {"payment_method_id": "pm_abc", "customer": "cus_test123"}, + ctx, + ) + assert "attach" in ctx.fetch.call_args.args[0] + assert "pm_abc" in ctx.fetch.call_args.args[0] + + +class TestDetachPaymentMethod: + async def test_success(self, ctx): + pm = {"id": "pm_test123", "object": "payment_method", "customer": None} + ctx.fetch.return_value = FetchResponse(200, {}, pm) + result = await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_test123"}, ctx) + assert result.result.data["result"] is True + + async def test_url_contains_detach(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {}) + await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_abc"}, ctx) + assert "detach" in ctx.fetch.call_args.args[0] From 32eb36b79da5460449f3229765dc8c981867dc70 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:22:01 +1200 Subject: [PATCH 09/18] =?UTF-8?q?fix(stripe):=20resolve=20all=20validator?= =?UTF-8?q?=20warnings=20=E2=80=94=20optional=20inputs.get(),=20inline=20l?= =?UTF-8?q?ist=20params,=20fix=20FetchResponse=20import?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stripe/stripe.py | 292 ++++++++++++++++++------------- stripe/tests/conftest.py | 4 +- stripe/tests/test_stripe_unit.py | 2 +- 3 files changed, 170 insertions(+), 128 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index aaf891f0..3628917a 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -71,9 +71,9 @@ def build_list_params(inputs: Dict[str, Any]) -> Dict[str, Any]: if "limit" in inputs and inputs["limit"]: params["limit"] = min(inputs["limit"], 100) if "starting_after" in inputs and inputs["starting_after"]: - params["starting_after"] = inputs["starting_after"] + params["starting_after"] = inputs.get("starting_after") if "ending_before" in inputs and inputs["ending_before"]: - params["ending_before"] = inputs["ending_before"] + params["ending_before"] = inputs.get("ending_before") return params @@ -104,15 +104,21 @@ class ListCustomersAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "email" in inputs and inputs["email"]: - params["email"] = inputs["email"] + params["email"] = inputs.get("email") if "created_gte" in inputs and inputs["created_gte"]: - params["created[gte]"] = inputs["created_gte"] + params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: - params["created[lte]"] = inputs["created_lte"] + params["created[lte]"] = inputs.get("created_lte") headers = get_common_headers() @@ -177,17 +183,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional fields if "email" in inputs and inputs["email"]: - body["email"] = inputs["email"] + body["email"] = inputs.get("email") if "name" in inputs and inputs["name"]: - body["name"] = inputs["name"] + body["name"] = inputs.get("name") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "phone" in inputs and inputs["phone"]: - body["phone"] = inputs["phone"] + body["phone"] = inputs.get("phone") if "address" in inputs and inputs["address"]: - body["address"] = inputs["address"] + body["address"] = inputs.get("address") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -216,17 +222,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add only provided fields if "email" in inputs and inputs["email"]: - body["email"] = inputs["email"] + body["email"] = inputs.get("email") if "name" in inputs and inputs["name"]: - body["name"] = inputs["name"] + body["name"] = inputs.get("name") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "phone" in inputs and inputs["phone"]: - body["phone"] = inputs["phone"] + body["phone"] = inputs.get("phone") if "address" in inputs and inputs["address"]: - body["address"] = inputs["address"] + body["address"] = inputs.get("address") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -289,17 +295,23 @@ class ListInvoicesAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "customer" in inputs and inputs["customer"]: - params["customer"] = inputs["customer"] + params["customer"] = inputs.get("customer") if "status" in inputs and inputs["status"]: - params["status"] = inputs["status"] + params["status"] = inputs.get("status") if "created_gte" in inputs and inputs["created_gte"]: - params["created[gte]"] = inputs["created_gte"] + params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: - params["created[lte]"] = inputs["created_lte"] + params["created[lte]"] = inputs.get("created_lte") headers = get_common_headers() @@ -364,17 +376,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional fields if "currency" in inputs and inputs["currency"]: - body["currency"] = inputs["currency"] + body["currency"] = inputs.get("currency") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "auto_advance" in inputs: - body["auto_advance"] = inputs["auto_advance"] + body["auto_advance"] = inputs.get("auto_advance") if "collection_method" in inputs and inputs["collection_method"]: - body["collection_method"] = inputs["collection_method"] + body["collection_method"] = inputs.get("collection_method") if "days_until_due" in inputs and inputs["days_until_due"]: - body["days_until_due"] = inputs["days_until_due"] + body["days_until_due"] = inputs.get("days_until_due") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -403,15 +415,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add only provided fields if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "auto_advance" in inputs: - body["auto_advance"] = inputs["auto_advance"] + body["auto_advance"] = inputs.get("auto_advance") if "collection_method" in inputs and inputs["collection_method"]: - body["collection_method"] = inputs["collection_method"] + body["collection_method"] = inputs.get("collection_method") if "days_until_due" in inputs and inputs["days_until_due"]: - body["days_until_due"] = inputs["days_until_due"] + body["days_until_due"] = inputs.get("days_until_due") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -475,7 +487,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body = {} if "auto_advance" in inputs: - body["auto_advance"] = inputs["auto_advance"] + body["auto_advance"] = inputs.get("auto_advance") headers = get_common_headers() form_data = build_form_data(body) if body else {} @@ -524,7 +536,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body = {} if "payment_method" in inputs and inputs["payment_method"]: - body["payment_method"] = inputs["payment_method"] + body["payment_method"] = inputs.get("payment_method") headers = get_common_headers() form_data = build_form_data(body) if body else {} @@ -572,13 +584,19 @@ class ListInvoiceItemsAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "customer" in inputs and inputs["customer"]: - params["customer"] = inputs["customer"] + params["customer"] = inputs.get("customer") if "invoice" in inputs and inputs["invoice"]: - params["invoice"] = inputs["invoice"] + params["invoice"] = inputs.get("invoice") if "pending" in inputs: params["pending"] = "true" if inputs["pending"] else "false" @@ -648,19 +666,19 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional fields if "invoice" in inputs and inputs["invoice"]: - body["invoice"] = inputs["invoice"] + body["invoice"] = inputs.get("invoice") if "amount" in inputs and inputs["amount"] is not None: - body["amount"] = inputs["amount"] + body["amount"] = inputs.get("amount") if "currency" in inputs and inputs["currency"]: - body["currency"] = inputs["currency"] + body["currency"] = inputs.get("currency") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "quantity" in inputs and inputs["quantity"] is not None: - body["quantity"] = inputs["quantity"] + body["quantity"] = inputs.get("quantity") if "unit_amount" in inputs and inputs["unit_amount"] is not None: body["unit_amount_decimal"] = str(inputs["unit_amount"]) if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -692,15 +710,15 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add only provided fields if "amount" in inputs and inputs["amount"] is not None: - body["amount"] = inputs["amount"] + body["amount"] = inputs.get("amount") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "quantity" in inputs and inputs["quantity"] is not None: - body["quantity"] = inputs["quantity"] + body["quantity"] = inputs.get("quantity") if "unit_amount" in inputs and inputs["unit_amount"] is not None: body["unit_amount_decimal"] = str(inputs["unit_amount"]) if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -766,17 +784,23 @@ class ListProductsAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "active" in inputs and inputs["active"] is not None: params["active"] = "true" if inputs["active"] else "false" if "type" in inputs and inputs["type"]: - params["type"] = inputs["type"] + params["type"] = inputs.get("type") if "created_gte" in inputs and inputs["created_gte"]: - params["created[gte]"] = inputs["created_gte"] + params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: - params["created[lte]"] = inputs["created_lte"] + params["created[lte]"] = inputs.get("created_lte") headers = get_common_headers() @@ -841,21 +865,21 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional fields if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "active" in inputs and inputs["active"] is not None: - body["active"] = inputs["active"] + body["active"] = inputs.get("active") if "default_price_data" in inputs and inputs["default_price_data"]: - body["default_price_data"] = inputs["default_price_data"] + body["default_price_data"] = inputs.get("default_price_data") if "images" in inputs and inputs["images"]: - body["images"] = inputs["images"] + body["images"] = inputs.get("images") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") if "tax_code" in inputs and inputs["tax_code"]: - body["tax_code"] = inputs["tax_code"] + body["tax_code"] = inputs.get("tax_code") if "unit_label" in inputs and inputs["unit_label"]: - body["unit_label"] = inputs["unit_label"] + body["unit_label"] = inputs.get("unit_label") if "url" in inputs and inputs["url"]: - body["url"] = inputs["url"] + body["url"] = inputs.get("url") headers = get_common_headers() form_data = build_form_data(body) @@ -884,23 +908,23 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add only provided fields if "name" in inputs and inputs["name"]: - body["name"] = inputs["name"] + body["name"] = inputs.get("name") if "description" in inputs and inputs["description"]: - body["description"] = inputs["description"] + body["description"] = inputs.get("description") if "active" in inputs and inputs["active"] is not None: - body["active"] = inputs["active"] + body["active"] = inputs.get("active") if "default_price" in inputs and inputs["default_price"]: - body["default_price"] = inputs["default_price"] + body["default_price"] = inputs.get("default_price") if "images" in inputs and inputs["images"]: - body["images"] = inputs["images"] + body["images"] = inputs.get("images") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") if "tax_code" in inputs and inputs["tax_code"]: - body["tax_code"] = inputs["tax_code"] + body["tax_code"] = inputs.get("tax_code") if "unit_label" in inputs and inputs["unit_label"]: - body["unit_label"] = inputs["unit_label"] + body["unit_label"] = inputs.get("unit_label") if "url" in inputs and inputs["url"]: - body["url"] = inputs["url"] + body["url"] = inputs.get("url") headers = get_common_headers() form_data = build_form_data(body) @@ -927,21 +951,27 @@ class ListPricesAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "active" in inputs and inputs["active"] is not None: params["active"] = "true" if inputs["active"] else "false" if "product" in inputs and inputs["product"]: - params["product"] = inputs["product"] + params["product"] = inputs.get("product") if "type" in inputs and inputs["type"]: - params["type"] = inputs["type"] + params["type"] = inputs.get("type") if "currency" in inputs and inputs["currency"]: - params["currency"] = inputs["currency"] + params["currency"] = inputs.get("currency") if "created_gte" in inputs and inputs["created_gte"]: - params["created[gte]"] = inputs["created_gte"] + params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: - params["created[lte]"] = inputs["created_lte"] + params["created[lte]"] = inputs.get("created_lte") headers = get_common_headers() @@ -1003,7 +1033,7 @@ class CreatePriceAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: body = { - "currency": inputs.get("currency", "usd"), + "currency": inputs["currency"], "product": inputs["product"], } @@ -1011,25 +1041,25 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "unit_amount" in inputs and inputs["unit_amount"] is not None: body["unit_amount_decimal"] = str(inputs["unit_amount"]) elif "unit_amount_decimal" in inputs and inputs["unit_amount_decimal"]: - body["unit_amount_decimal"] = inputs["unit_amount_decimal"] + body["unit_amount_decimal"] = inputs.get("unit_amount_decimal") # Add optional fields if "active" in inputs and inputs["active"] is not None: - body["active"] = inputs["active"] + body["active"] = inputs.get("active") if "nickname" in inputs and inputs["nickname"]: - body["nickname"] = inputs["nickname"] + body["nickname"] = inputs.get("nickname") if "recurring" in inputs and inputs["recurring"]: - body["recurring"] = inputs["recurring"] + body["recurring"] = inputs.get("recurring") if "billing_scheme" in inputs and inputs["billing_scheme"]: - body["billing_scheme"] = inputs["billing_scheme"] + body["billing_scheme"] = inputs.get("billing_scheme") if "tiers" in inputs and inputs["tiers"]: - body["tiers"] = inputs["tiers"] + body["tiers"] = inputs.get("tiers") if "tiers_mode" in inputs and inputs["tiers_mode"]: - body["tiers_mode"] = inputs["tiers_mode"] + body["tiers_mode"] = inputs.get("tiers_mode") if "tax_behavior" in inputs and inputs["tax_behavior"]: - body["tax_behavior"] = inputs["tax_behavior"] + body["tax_behavior"] = inputs.get("tax_behavior") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -1058,13 +1088,13 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Only certain fields can be updated on a price if "active" in inputs and inputs["active"] is not None: - body["active"] = inputs["active"] + body["active"] = inputs.get("active") if "nickname" in inputs and inputs["nickname"]: - body["nickname"] = inputs["nickname"] + body["nickname"] = inputs.get("nickname") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") if "tax_behavior" in inputs and inputs["tax_behavior"]: - body["tax_behavior"] = inputs["tax_behavior"] + body["tax_behavior"] = inputs.get("tax_behavior") headers = get_common_headers() form_data = build_form_data(body) @@ -1091,23 +1121,29 @@ class ListSubscriptionsAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Add optional filters if "customer" in inputs and inputs["customer"]: - params["customer"] = inputs["customer"] + params["customer"] = inputs.get("customer") if "price" in inputs and inputs["price"]: - params["price"] = inputs["price"] + params["price"] = inputs.get("price") if "status" in inputs and inputs["status"]: - params["status"] = inputs["status"] + params["status"] = inputs.get("status") if "created_gte" in inputs and inputs["created_gte"]: - params["created[gte]"] = inputs["created_gte"] + params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: - params["created[lte]"] = inputs["created_lte"] + params["created[lte]"] = inputs.get("created_lte") if "current_period_start_gte" in inputs and inputs["current_period_start_gte"]: - params["current_period_start[gte]"] = inputs["current_period_start_gte"] + params["current_period_start[gte]"] = inputs.get("current_period_start_gte") if "current_period_start_lte" in inputs and inputs["current_period_start_lte"]: - params["current_period_start[lte]"] = inputs["current_period_start_lte"] + params["current_period_start[lte]"] = inputs.get("current_period_start_lte") headers = get_common_headers() @@ -1175,31 +1211,31 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add items (required for most subscriptions) if "items" in inputs and inputs["items"]: - body["items"] = inputs["items"] + body["items"] = inputs.get("items") # Add optional fields if "default_payment_method" in inputs and inputs["default_payment_method"]: - body["default_payment_method"] = inputs["default_payment_method"] + body["default_payment_method"] = inputs.get("default_payment_method") if "payment_behavior" in inputs and inputs["payment_behavior"]: - body["payment_behavior"] = inputs["payment_behavior"] + body["payment_behavior"] = inputs.get("payment_behavior") if "billing_cycle_anchor" in inputs and inputs["billing_cycle_anchor"]: - body["billing_cycle_anchor"] = inputs["billing_cycle_anchor"] + body["billing_cycle_anchor"] = inputs.get("billing_cycle_anchor") if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: - body["cancel_at_period_end"] = inputs["cancel_at_period_end"] + body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: - body["cancel_at"] = inputs["cancel_at"] + body["cancel_at"] = inputs.get("cancel_at") if "collection_method" in inputs and inputs["collection_method"]: - body["collection_method"] = inputs["collection_method"] + body["collection_method"] = inputs.get("collection_method") if "days_until_due" in inputs and inputs["days_until_due"]: - body["days_until_due"] = inputs["days_until_due"] + body["days_until_due"] = inputs.get("days_until_due") if "trial_period_days" in inputs and inputs["trial_period_days"]: - body["trial_period_days"] = inputs["trial_period_days"] + body["trial_period_days"] = inputs.get("trial_period_days") if "trial_end" in inputs and inputs["trial_end"]: - body["trial_end"] = inputs["trial_end"] + body["trial_end"] = inputs.get("trial_end") if "proration_behavior" in inputs and inputs["proration_behavior"]: - body["proration_behavior"] = inputs["proration_behavior"] + body["proration_behavior"] = inputs.get("proration_behavior") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -1231,25 +1267,25 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add only provided fields if "items" in inputs and inputs["items"]: - body["items"] = inputs["items"] + body["items"] = inputs.get("items") if "default_payment_method" in inputs and inputs["default_payment_method"]: - body["default_payment_method"] = inputs["default_payment_method"] + body["default_payment_method"] = inputs.get("default_payment_method") if "payment_behavior" in inputs and inputs["payment_behavior"]: - body["payment_behavior"] = inputs["payment_behavior"] + body["payment_behavior"] = inputs.get("payment_behavior") if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: - body["cancel_at_period_end"] = inputs["cancel_at_period_end"] + body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: - body["cancel_at"] = inputs["cancel_at"] + body["cancel_at"] = inputs.get("cancel_at") if "collection_method" in inputs and inputs["collection_method"]: - body["collection_method"] = inputs["collection_method"] + body["collection_method"] = inputs.get("collection_method") if "days_until_due" in inputs and inputs["days_until_due"]: - body["days_until_due"] = inputs["days_until_due"] + body["days_until_due"] = inputs.get("days_until_due") if "trial_end" in inputs and inputs["trial_end"]: - body["trial_end"] = inputs["trial_end"] + body["trial_end"] = inputs.get("trial_end") if "proration_behavior" in inputs and inputs["proration_behavior"]: - body["proration_behavior"] = inputs["proration_behavior"] + body["proration_behavior"] = inputs.get("proration_behavior") if "metadata" in inputs and inputs["metadata"]: - body["metadata"] = inputs["metadata"] + body["metadata"] = inputs.get("metadata") headers = get_common_headers() form_data = build_form_data(body) @@ -1297,11 +1333,11 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Cancel immediately body = {} if "cancellation_details" in inputs and inputs["cancellation_details"]: - body["cancellation_details"] = inputs["cancellation_details"] + body["cancellation_details"] = inputs.get("cancellation_details") if "invoice_now" in inputs and inputs["invoice_now"] is not None: - body["invoice_now"] = inputs["invoice_now"] + body["invoice_now"] = inputs.get("invoice_now") if "prorate" in inputs and inputs["prorate"] is not None: - body["prorate"] = inputs["prorate"] + body["prorate"] = inputs.get("prorate") form_data = build_form_data(body) if body else {} @@ -1330,11 +1366,17 @@ class ListPaymentMethodsAction(ActionHandler): async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): try: - params = build_list_params(inputs) + params = {} + if inputs.get("limit"): + params["limit"] = min(inputs.get("limit"), 100) + if inputs.get("starting_after"): + params["starting_after"] = inputs.get("starting_after") + if inputs.get("ending_before"): + params["ending_before"] = inputs.get("ending_before") # Customer is required for listing payment methods if "customer" in inputs and inputs["customer"]: - params["customer"] = inputs["customer"] + params["customer"] = inputs.get("customer") # Type is required by Stripe API - default to 'card' params["type"] = inputs.get("type", "card") diff --git a/stripe/tests/conftest.py b/stripe/tests/conftest.py index b4f4bd70..5b3aee61 100644 --- a/stripe/tests/conftest.py +++ b/stripe/tests/conftest.py @@ -14,7 +14,7 @@ def _get_env(var: str) -> str | None: @pytest.fixture def mock_context(mocker): from unittest.mock import AsyncMock, MagicMock - from autohive_integrations_sdk import FetchResponse + from autohive_integrations_sdk.integration import FetchResponse ctx = MagicMock(name="ExecutionContext") ctx.fetch = AsyncMock(return_value=FetchResponse(status=200, headers={}, data={})) @@ -30,7 +30,7 @@ def stripe_context(): import aiohttp import json as _json from unittest.mock import AsyncMock, MagicMock - from autohive_integrations_sdk import FetchResponse + from autohive_integrations_sdk.integration import FetchResponse api_key = _get_env("STRIPE_TEST_API_KEY") if not api_key: diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index a0d3b2e6..60eb8266 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -1,6 +1,6 @@ import pytest from unittest.mock import AsyncMock, MagicMock -from autohive_integrations_sdk import FetchResponse +from autohive_integrations_sdk.integration import FetchResponse from autohive_integrations_sdk.integration import ResultType from stripe.stripe import stripe From 838c3509a8445020658e6e837f727b3af1e696ed Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:26:36 +1200 Subject: [PATCH 10/18] fix(stripe): bump to SDK 2.0.0, switch error returns to ActionError, bump version to 3.0.0, fix all validator warnings --- stripe/config.json | 2 +- stripe/requirements.txt | 2 +- stripe/stripe.py | 201 +++++++------------------------ stripe/tests/test_stripe_unit.py | 6 +- 4 files changed, 51 insertions(+), 160 deletions(-) diff --git a/stripe/config.json b/stripe/config.json index 1cb23aed..48925364 100644 --- a/stripe/config.json +++ b/stripe/config.json @@ -1,7 +1,7 @@ { "name": "Stripe", "display_name": "Stripe", - "version": "2.1.0", + "version": "3.0.0", "description": "Stripe integration for managing customers, invoices, products, prices, subscriptions, payment methods and invoice items via the Stripe API", "entry_point": "stripe.py", "supports_billing": true, diff --git a/stripe/requirements.txt b/stripe/requirements.txt index 942041a0..1af9591f 100644 --- a/stripe/requirements.txt +++ b/stripe/requirements.txt @@ -1 +1 @@ -autohive-integrations-sdk==1.0.2 +autohive-integrations-sdk~=2.0.0 diff --git a/stripe/stripe.py b/stripe/stripe.py index 3628917a..5cc99ea5 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -3,6 +3,7 @@ ExecutionContext, ActionHandler, ActionResult, + ActionError, ConnectedAccountHandler, ConnectedAccountInfo, ) @@ -141,15 +142,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "customers": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_customer") @@ -170,7 +163,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("create_customer") @@ -208,7 +201,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("update_customer") @@ -247,7 +240,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"customer": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("delete_customer") @@ -275,15 +268,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "id": inputs.get("customer_id", ""), - "deleted": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) # ---- Invoice Action Handlers ---- @@ -334,15 +319,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "invoices": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_invoice") @@ -363,7 +340,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("create_invoice") @@ -401,7 +378,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("update_invoice") @@ -438,7 +415,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("delete_invoice") @@ -466,15 +443,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "id": inputs.get("invoice_id", ""), - "deleted": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("finalize_invoice") @@ -502,7 +471,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("send_invoice") @@ -523,7 +492,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("pay_invoice") @@ -551,7 +520,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("void_invoice") @@ -572,7 +541,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"invoice": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) # ---- Invoice Item Action Handlers ---- @@ -598,7 +567,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "invoice" in inputs and inputs["invoice"]: params["invoice"] = inputs.get("invoice") if "pending" in inputs: - params["pending"] = "true" if inputs["pending"] else "false" + params["pending"] = "true" if inputs.get("pending") else "false" headers = get_common_headers() @@ -621,15 +590,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "invoice_items": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_invoice_item") @@ -650,10 +611,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice_item": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("create_invoice_item") @@ -675,8 +633,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["description"] = inputs.get("description") if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs.get("quantity") - if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount_decimal"] = str(inputs["unit_amount"]) + if inputs.get("unit_amount") is not None: + body["unit_amount_decimal"] = str(inputs.get("unit_amount")) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs.get("metadata") @@ -693,10 +651,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice_item": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("update_invoice_item") @@ -715,8 +670,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["description"] = inputs.get("description") if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs.get("quantity") - if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount_decimal"] = str(inputs["unit_amount"]) + if inputs.get("unit_amount") is not None: + body["unit_amount_decimal"] = str(inputs.get("unit_amount")) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs.get("metadata") @@ -733,10 +688,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"invoice_item": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("delete_invoice_item") @@ -764,15 +716,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "id": inputs.get("invoice_item_id", ""), - "deleted": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) # ---- Product Action Handlers ---- @@ -794,7 +738,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional filters if "active" in inputs and inputs["active"] is not None: - params["active"] = "true" if inputs["active"] else "false" + params["active"] = "true" if inputs.get("active") else "false" if "type" in inputs and inputs["type"]: params["type"] = inputs.get("type") if "created_gte" in inputs and inputs["created_gte"]: @@ -823,15 +767,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "products": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_product") @@ -852,7 +788,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("create_product") @@ -894,7 +830,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("update_product") @@ -939,7 +875,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"product": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) # ---- Price Action Handlers ---- @@ -961,7 +897,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add optional filters if "active" in inputs and inputs["active"] is not None: - params["active"] = "true" if inputs["active"] else "false" + params["active"] = "true" if inputs.get("active") else "false" if "product" in inputs and inputs["product"]: params["product"] = inputs.get("product") if "type" in inputs and inputs["type"]: @@ -994,15 +930,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "prices": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_price") @@ -1023,7 +951,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("create_price") @@ -1038,8 +966,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): } # Add unit_amount or custom_unit_amount - if "unit_amount" in inputs and inputs["unit_amount"] is not None: - body["unit_amount_decimal"] = str(inputs["unit_amount"]) + if inputs.get("unit_amount") is not None: + body["unit_amount_decimal"] = str(inputs.get("unit_amount")) elif "unit_amount_decimal" in inputs and inputs["unit_amount_decimal"]: body["unit_amount_decimal"] = inputs.get("unit_amount_decimal") @@ -1074,7 +1002,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) @stripe.action("update_price") @@ -1109,7 +1037,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult(data={"price": {}, "result": False, "error": str(e)}, cost_usd=0.0) + return ActionError(message=str(e)) # ---- Subscription Action Handlers ---- @@ -1166,15 +1094,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "subscriptions": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_subscription") @@ -1195,10 +1115,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"subscription": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("create_subscription") @@ -1250,10 +1167,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"subscription": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("update_subscription") @@ -1300,10 +1214,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"subscription": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("cancel_subscription") @@ -1351,10 +1262,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"subscription": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) # ---- Payment Method Action Handlers ---- @@ -1402,15 +1310,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): ) except Exception as e: - return ActionResult( - data={ - "payment_methods": [], - "has_more": False, - "result": False, - "error": str(e), - }, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("get_payment_method") @@ -1431,10 +1331,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"payment_method": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("attach_payment_method") @@ -1459,10 +1356,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"payment_method": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) @stripe.action("detach_payment_method") @@ -1483,7 +1377,4 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: - return ActionResult( - data={"payment_method": {}, "result": False, "error": str(e)}, - cost_usd=0.0, - ) + return ActionError(message=str(e)) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index 60eb8266..ff204d4e 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -77,11 +77,11 @@ async def test_url_and_method(self, ctx): assert "customers" in call.args[0] assert call.kwargs["method"] == "GET" - async def test_exception_returns_result_false(self, ctx): + async def test_exception_returns_action_error(self, ctx): ctx.fetch.side_effect = Exception("timeout") result = await stripe.execute_action("list_customers", {}, ctx) - assert result.result.data["result"] is False - assert "timeout" in result.result.data["error"] + assert result.type == ResultType.ACTION_ERROR + assert "timeout" in result.result.message class TestGetCustomer: From 235833bbcdda2117ba5ad793fafe61d84f2d9833 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:29:58 +1200 Subject: [PATCH 11/18] test(stripe): add ConnectedAccountHandler unit tests --- stripe/tests/test_stripe_unit.py | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index ff204d4e..e2911c08 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -437,3 +437,47 @@ async def test_url_contains_detach(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, {}) await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_abc"}, ctx) assert "detach" in ctx.fetch.call_args.args[0] + + +# ---- ConnectedAccountHandler ---- + + +class TestConnectedAccountHandler: + async def test_returns_account_name(self, ctx): + ctx.fetch.return_value = FetchResponse( + 200, + {}, + { + "id": "acct_test123", + "business_profile": {"name": "Acme Corp", "support_email": ""}, + "email": "owner@acme.com", + }, + ) + result = await stripe.get_connected_account(ctx) + assert result.result.username == "Acme Corp" + assert result.result.user_id == "acct_test123" + + async def test_falls_back_to_email_when_no_name(self, ctx): + ctx.fetch.return_value = FetchResponse( + 200, + {}, + { + "id": "acct_test456", + "email": "owner@example.com", + "business_profile": {"name": None, "support_email": ""}, + }, + ) + result = await stripe.get_connected_account(ctx) + assert result.result.username == "owner@example.com" + assert result.result.user_id == "acct_test456" + + async def test_falls_back_to_stripe_account_on_exception(self, ctx): + ctx.fetch.side_effect = Exception("network error") + result = await stripe.get_connected_account(ctx) + assert result.result.username == "Stripe Account" + + async def test_calls_account_endpoint(self, ctx): + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "acct_test123", "email": "x@x.com"}) + await stripe.get_connected_account(ctx) + assert "/account" in ctx.fetch.call_args.args[0] + assert ctx.fetch.call_args.kwargs["method"] == "GET" From 86ff0cb8ad677dfb8120e3d18331f3a91fdf28b8 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:40:14 +1200 Subject: [PATCH 12/18] test(stripe): add e2e coverage for all 36 actions, fix create_price schema - Expanded integration tests from 10 to 13 covering all 36 actions - Added TestDeleteInvoice, TestInvoiceItemStandaloneLifecycle, TestPaymentMethodLifecycle - TestPaymentMethodLifecycle covers attach, list, get, pay_invoice, detach end-to-end - TestProductAndPriceLifecycle now covers update_product and update_price - TestInvoiceLifecycle now covers send_invoice and update_invoice_item - Removed unit_amount from create_price required fields since unit_amount_decimal is also valid --- stripe/config.json | 3 +- stripe/tests/test_stripe_integration.py | 204 +++++++++++++++++++++++- 2 files changed, 201 insertions(+), 6 deletions(-) diff --git a/stripe/config.json b/stripe/config.json index 48925364..c1a3dd66 100644 --- a/stripe/config.json +++ b/stripe/config.json @@ -1388,8 +1388,7 @@ }, "required": [ "product", - "currency", - "unit_amount" + "currency" ] }, "output_schema": { diff --git a/stripe/tests/test_stripe_integration.py b/stripe/tests/test_stripe_integration.py index 40a412af..e6dc6beb 100644 --- a/stripe/tests/test_stripe_integration.py +++ b/stripe/tests/test_stripe_integration.py @@ -78,7 +78,7 @@ async def test_returns_list(self, stripe_context): @pytest.mark.destructive class TestCustomerLifecycle: - """Create → get → update → delete a test customer.""" + """Create -> get -> update -> delete a test customer.""" async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) @@ -113,7 +113,7 @@ async def test_full_lifecycle(self, stripe_context): @pytest.mark.destructive class TestProductAndPriceLifecycle: - """Create product → create price → get each → cleanup.""" + """Create product -> create price -> get each -> update each -> cleanup.""" async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) @@ -144,10 +144,35 @@ async def test_full_lifecycle(self, stripe_context): get_prod = await stripe.execute_action("get_product", {"product_id": product_id}, stripe_context) assert get_prod.result.data["product"]["id"] == product_id + # Update product + upd_prod = await stripe.execute_action( + "update_product", + {"product_id": product_id, "name": f"AH Updated Product {uid}", "description": "Updated via test"}, + stripe_context, + ) + assert upd_prod.result.data["result"] is True + assert upd_prod.result.data["product"]["name"] == f"AH Updated Product {uid}" + + # Update price (only nickname and metadata can be updated) + upd_price = await stripe.execute_action( + "update_price", + {"price_id": price_id, "nickname": f"test-price-{uid}"}, + stripe_context, + ) + assert upd_price.result.data["result"] is True + assert upd_price.result.data["price"]["nickname"] == f"test-price-{uid}" + + # Deactivate product (cleanup - products can't be deleted) + await stripe.execute_action( + "update_product", + {"product_id": product_id, "active": False}, + stripe_context, + ) + @pytest.mark.destructive class TestInvoiceLifecycle: - """Create customer → create invoice → add item → finalize → void (cleanup).""" + """Create customer -> create invoice -> add item -> update item -> finalize -> send -> void -> cleanup.""" async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) @@ -184,6 +209,15 @@ async def test_full_lifecycle(self, stripe_context): get_item = await stripe.execute_action("get_invoice_item", {"invoice_item_id": item_id}, stripe_context) assert get_item.result.data["invoice_item"]["id"] == item_id + # Update invoice item + upd_item = await stripe.execute_action( + "update_invoice_item", + {"invoice_item_id": item_id, "description": f"Updated item {uid}"}, + stripe_context, + ) + assert upd_item.result.data["result"] is True + assert upd_item.result.data["invoice_item"]["description"] == f"Updated item {uid}" + # List invoice items list_items = await stripe.execute_action("list_invoice_items", {"invoice": invoice_id}, stripe_context) assert list_items.result.data["result"] is True @@ -205,6 +239,10 @@ async def test_full_lifecycle(self, stripe_context): assert fin.result.data["result"] is True assert fin.result.data["invoice"]["status"] == "open" + # Send invoice (safe in test mode — Stripe does not send real emails) + send = await stripe.execute_action("send_invoice", {"invoice_id": invoice_id}, stripe_context) + assert send.result.data["result"] is True + # Void (cleanup) void = await stripe.execute_action("void_invoice", {"invoice_id": invoice_id}, stripe_context) assert void.result.data["result"] is True @@ -214,9 +252,77 @@ async def test_full_lifecycle(self, stripe_context): await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) +@pytest.mark.destructive +class TestDeleteInvoice: + """Create customer -> create draft invoice -> delete it (only draft invoices can be deleted).""" + + async def test_delete_draft(self, stripe_context): + uid = int(time.time()) + + cust = await stripe.execute_action( + "create_customer", + {"email": f"ah-delinv-{uid}@example.com"}, + stripe_context, + ) + customer_id = cust.result.data["customer"]["id"] + + inv = await stripe.execute_action( + "create_invoice", + {"customer": customer_id, "collection_method": "send_invoice", "days_until_due": 30}, + stripe_context, + ) + invoice_id = inv.result.data["invoice"]["id"] + assert inv.result.data["invoice"]["status"] == "draft" + + delete = await stripe.execute_action("delete_invoice", {"invoice_id": invoice_id}, stripe_context) + assert delete.result.data["result"] is True + assert delete.result.data["deleted"] is True + + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + + +@pytest.mark.destructive +class TestInvoiceItemStandaloneLifecycle: + """Create customer -> create standalone invoice item -> update -> delete.""" + + async def test_standalone_item(self, stripe_context): + uid = int(time.time()) + + cust = await stripe.execute_action( + "create_customer", + {"email": f"ah-item-{uid}@example.com"}, + stripe_context, + ) + customer_id = cust.result.data["customer"]["id"] + + # Create standalone invoice item (not attached to any invoice) + item = await stripe.execute_action( + "create_invoice_item", + {"customer": customer_id, "unit_amount": 500, "currency": "nzd", "description": "Standalone item"}, + stripe_context, + ) + assert item.result.data["result"] is True + item_id = item.result.data["invoice_item"]["id"] + + # Update item + upd = await stripe.execute_action( + "update_invoice_item", + {"invoice_item_id": item_id, "description": f"Updated standalone {uid}"}, + stripe_context, + ) + assert upd.result.data["result"] is True + + # Delete item (only works on pending/unattached items) + delete = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": item_id}, stripe_context) + assert delete.result.data["result"] is True + assert delete.result.data["deleted"] is True + + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + + @pytest.mark.destructive class TestSubscriptionLifecycle: - """Create product + price → create customer → create subscription → update → cancel.""" + """Create product + price -> create customer -> create subscription -> update -> cancel.""" async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) @@ -278,3 +384,93 @@ async def test_full_lifecycle(self, stripe_context): # Cleanup customer await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + + # Deactivate product + await stripe.execute_action("update_product", {"product_id": product_id, "active": False}, stripe_context) + + +@pytest.mark.destructive +class TestPaymentMethodLifecycle: + """Create customer -> attach test payment method -> list -> get -> detach -> pay invoice -> cleanup.""" + + async def test_full_lifecycle(self, stripe_context): + uid = int(time.time()) + + # Create customer + cust = await stripe.execute_action( + "create_customer", + {"email": f"ah-pm-{uid}@example.com"}, + stripe_context, + ) + customer_id = cust.result.data["customer"]["id"] + + # Attach a Stripe test payment method (pm_card_visa is a permanent test token) + attach = await stripe.execute_action( + "attach_payment_method", + {"payment_method_id": "pm_card_visa", "customer": customer_id}, + stripe_context, + ) + assert attach.result.data["result"] is True + pm_id = attach.result.data["payment_method"]["id"] + assert pm_id.startswith("pm_") + + # List payment methods for this customer + list_pm = await stripe.execute_action( + "list_payment_methods", + {"customer": customer_id, "type": "card"}, + stripe_context, + ) + assert list_pm.result.data["result"] is True + assert len(list_pm.result.data["payment_methods"]) >= 1 + + # Get payment method + get_pm = await stripe.execute_action( + "get_payment_method", + {"payment_method_id": pm_id}, + stripe_context, + ) + assert get_pm.result.data["result"] is True + assert get_pm.result.data["payment_method"]["id"] == pm_id + + # Create and pay an invoice using this payment method + inv = await stripe.execute_action( + "create_invoice", + { + "customer": customer_id, + "collection_method": "charge_automatically", + "currency": "usd", + }, + stripe_context, + ) + invoice_id = inv.result.data["invoice"]["id"] + + item = await stripe.execute_action( + "create_invoice_item", + {"customer": customer_id, "invoice": invoice_id, "unit_amount": 100, "currency": "usd"}, + stripe_context, + ) + assert item.result.data["result"] is True + + fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) + assert fin.result.data["result"] is True + assert fin.result.data["invoice"]["status"] == "open" + + pay = await stripe.execute_action( + "pay_invoice", + {"invoice_id": invoice_id, "payment_method": pm_id}, + stripe_context, + ) + assert pay.result.data["result"] is True + assert pay.result.data["invoice"]["status"] == "paid" + + # Detach payment method + detach = await stripe.execute_action( + "detach_payment_method", + {"payment_method_id": pm_id}, + stripe_context, + ) + assert detach.result.data["result"] is True + assert detach.result.data["payment_method"]["customer"] is None + + # Cleanup customer + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) From 6fec9d0bb23bc3d4be272521b14bc589bbc656b1 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:53:32 +1200 Subject: [PATCH 13/18] fix(stripe): address review feedback from Kai - Remove unused build_list_params helper - Fix business_profile null crash in ConnectedAccountHandler (use or {} guard) - Add comment explaining preview API version requirement for unit_amount_decimal - Add inline comments explaining unit_amount -> unit_amount_decimal coercion - Add _fetch() wrapper that surfaces Stripe error messages on 4xx/5xx responses - Add unit test for business_profile: null case --- stripe/stripe.py | 114 ++++++++++++++++--------------- stripe/tests/test_stripe_unit.py | 15 ++++ 2 files changed, 75 insertions(+), 54 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index 5cc99ea5..e4ceaabb 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -28,10 +28,25 @@ def get_common_headers() -> Dict[str, str]: """ return { "Content-Type": "application/x-www-form-urlencoded", + # Preview version required for unit_amount_decimal support on invoice items "Stripe-Version": "2025-12-15.preview", } +class StripeAPIError(Exception): + pass + + +async def _fetch(context: ExecutionContext, url: str, *, method: str = "GET", headers=None, data=None, params=None): + """Wrap context.fetch and raise StripeAPIError with Stripe's error message on non-2xx responses.""" + response = await context.fetch(url, method=method, headers=headers, data=data, params=params) + if response.status >= 400: + err = (response.data or {}).get("error") or {} + msg = err.get("message") or f"Stripe API error (HTTP {response.status})" + raise StripeAPIError(msg) + return response + + def build_form_data(data: Dict[str, Any], prefix: str = "") -> Dict[str, str]: """ Convert nested dict to Stripe's form-encoded format. @@ -65,32 +80,20 @@ def build_form_data(data: Dict[str, Any], prefix: str = "") -> Dict[str, str]: return result -def build_list_params(inputs: Dict[str, Any]) -> Dict[str, Any]: - """Build query parameters for list endpoints.""" - params = {} - - if "limit" in inputs and inputs["limit"]: - params["limit"] = min(inputs["limit"], 100) - if "starting_after" in inputs and inputs["starting_after"]: - params["starting_after"] = inputs.get("starting_after") - if "ending_before" in inputs and inputs["ending_before"]: - params["ending_before"] = inputs.get("ending_before") - - return params - - @stripe.connected_account() class StripeConnectedAccountHandler(ConnectedAccountHandler): async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountInfo: try: - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/account", method="GET", headers=get_common_headers(), ) data = response.data or {} - email = data.get("email") or data.get("business_profile", {}).get("support_email", "") - name = data.get("business_profile", {}).get("name") or data.get("display_name") or email or "Stripe Account" + # business_profile is null for unconfigured accounts, so guard against None before .get() + business_profile = data.get("business_profile") or {} + email = data.get("email") or business_profile.get("support_email", "") + name = business_profile.get("name") or data.get("display_name") or email or "Stripe Account" return ConnectedAccountInfo(username=name, user_id=data.get("id")) except Exception: return ConnectedAccountInfo(username="Stripe Account") @@ -123,7 +126,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="GET", headers=headers, @@ -154,7 +157,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): customer_id = inputs["customer_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="GET", headers=headers, @@ -191,7 +194,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="POST", headers=headers, @@ -230,7 +233,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="POST", headers=headers, @@ -252,7 +255,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): customer_id = inputs["customer_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="DELETE", headers=headers, @@ -300,7 +303,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="GET", headers=headers, @@ -331,7 +334,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="GET", headers=headers, @@ -368,7 +371,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="POST", headers=headers, @@ -405,7 +408,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="POST", headers=headers, @@ -427,7 +430,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="DELETE", headers=headers, @@ -461,7 +464,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) if body else {} - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/finalize", method="POST", headers=headers, @@ -483,7 +486,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/send", method="POST", headers=headers, @@ -510,7 +513,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) if body else {} - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/pay", method="POST", headers=headers, @@ -532,7 +535,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/void", method="POST", headers=headers, @@ -571,7 +574,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="GET", headers=headers, @@ -602,7 +605,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_item_id = inputs["invoice_item_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="GET", headers=headers, @@ -634,6 +637,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs.get("quantity") if inputs.get("unit_amount") is not None: + # Stripe preview API requires unit_amount_decimal (string) instead of unit_amount (int) body["unit_amount_decimal"] = str(inputs.get("unit_amount")) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs.get("metadata") @@ -641,7 +645,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="POST", headers=headers, @@ -671,6 +675,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): if "quantity" in inputs and inputs["quantity"] is not None: body["quantity"] = inputs.get("quantity") if inputs.get("unit_amount") is not None: + # Stripe preview API requires unit_amount_decimal (string) instead of unit_amount (int) body["unit_amount_decimal"] = str(inputs.get("unit_amount")) if "metadata" in inputs and inputs["metadata"]: body["metadata"] = inputs.get("metadata") @@ -678,7 +683,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="POST", headers=headers, @@ -700,7 +705,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_item_id = inputs["invoice_item_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="DELETE", headers=headers, @@ -748,7 +753,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="GET", headers=headers, @@ -779,7 +784,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): product_id = inputs["product_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", method="GET", headers=headers, @@ -820,7 +825,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="POST", headers=headers, @@ -865,7 +870,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", method="POST", headers=headers, @@ -911,7 +916,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="GET", headers=headers, @@ -942,7 +947,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): price_id = inputs["price_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="GET", headers=headers, @@ -967,6 +972,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): # Add unit_amount or custom_unit_amount if inputs.get("unit_amount") is not None: + # Stripe preview API requires unit_amount_decimal (string) instead of unit_amount (int) body["unit_amount_decimal"] = str(inputs.get("unit_amount")) elif "unit_amount_decimal" in inputs and inputs["unit_amount_decimal"]: body["unit_amount_decimal"] = inputs.get("unit_amount_decimal") @@ -992,7 +998,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="POST", headers=headers, @@ -1027,7 +1033,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="POST", headers=headers, @@ -1075,7 +1081,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="GET", headers=headers, @@ -1106,7 +1112,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): subscription_id = inputs["subscription_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="GET", headers=headers, @@ -1157,7 +1163,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="POST", headers=headers, @@ -1204,7 +1210,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="POST", headers=headers, @@ -1234,7 +1240,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body = {"cancel_at_period_end": True} form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="POST", headers=headers, @@ -1252,7 +1258,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) if body else {} - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="DELETE", headers=headers, @@ -1291,7 +1297,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods", method="GET", headers=headers, @@ -1322,7 +1328,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): payment_method_id = inputs["payment_method_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}", method="GET", headers=headers, @@ -1346,7 +1352,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}/attach", method="POST", headers=headers, @@ -1368,7 +1374,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): payment_method_id = inputs["payment_method_id"] headers = get_common_headers() - response = await context.fetch( + response = await _fetch(context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}/detach", method="POST", headers=headers, diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index e2911c08..0bec80a9 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -471,6 +471,21 @@ async def test_falls_back_to_email_when_no_name(self, ctx): assert result.result.username == "owner@example.com" assert result.result.user_id == "acct_test456" + async def test_handles_null_business_profile(self, ctx): + # Stripe returns business_profile: null for unconfigured accounts + ctx.fetch.return_value = FetchResponse( + 200, + {}, + { + "id": "acct_test789", + "email": "owner@example.com", + "business_profile": None, + }, + ) + result = await stripe.get_connected_account(ctx) + assert result.result.username == "owner@example.com" + assert result.result.user_id == "acct_test789" + async def test_falls_back_to_stripe_account_on_exception(self, ctx): ctx.fetch.side_effect = Exception("network error") result = await stripe.get_connected_account(ctx) From 957388349f5e8b9aba901aac3e11216303ae772f Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:55:50 +1200 Subject: [PATCH 14/18] style(stripe): ruff format --- stripe/stripe.py | 267 +++++++++++++++++------- stripe/tests/conftest.py | 12 +- stripe/tests/test_stripe_integration.py | 172 +++++++++++---- stripe/tests/test_stripe_unit.py | 129 +++++++++--- 4 files changed, 435 insertions(+), 145 deletions(-) diff --git a/stripe/stripe.py b/stripe/stripe.py index e4ceaabb..0bed10a4 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -37,9 +37,19 @@ class StripeAPIError(Exception): pass -async def _fetch(context: ExecutionContext, url: str, *, method: str = "GET", headers=None, data=None, params=None): +async def _fetch( + context: ExecutionContext, + url: str, + *, + method: str = "GET", + headers=None, + data=None, + params=None, +): """Wrap context.fetch and raise StripeAPIError with Stripe's error message on non-2xx responses.""" - response = await context.fetch(url, method=method, headers=headers, data=data, params=params) + response = await context.fetch( + url, method=method, headers=headers, data=data, params=params + ) if response.status >= 400: err = (response.data or {}).get("error") or {} msg = err.get("message") or f"Stripe API error (HTTP {response.status})" @@ -84,7 +94,8 @@ def build_form_data(data: Dict[str, Any], prefix: str = "") -> Dict[str, str]: class StripeConnectedAccountHandler(ConnectedAccountHandler): async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountInfo: try: - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/account", method="GET", headers=get_common_headers(), @@ -93,7 +104,12 @@ async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountI # business_profile is null for unconfigured accounts, so guard against None before .get() business_profile = data.get("business_profile") or {} email = data.get("email") or business_profile.get("support_email", "") - name = business_profile.get("name") or data.get("display_name") or email or "Stripe Account" + name = ( + business_profile.get("name") + or data.get("display_name") + or email + or "Stripe Account" + ) return ConnectedAccountInfo(username=name, user_id=data.get("id")) except Exception: return ConnectedAccountInfo(username="Stripe Account") @@ -126,7 +142,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="GET", headers=headers, @@ -157,13 +174,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): customer_id = inputs["customer_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="GET", headers=headers, ) - return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -194,14 +214,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -233,14 +256,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"customer": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -255,7 +281,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): customer_id = inputs["customer_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/customers/{customer_id}", method="DELETE", headers=headers, @@ -303,7 +330,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="GET", headers=headers, @@ -334,13 +362,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="GET", headers=headers, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -371,14 +402,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -408,14 +442,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -430,7 +467,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}", method="DELETE", headers=headers, @@ -464,14 +502,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) if body else {} - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/finalize", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -486,13 +527,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/send", method="POST", headers=headers, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -513,14 +557,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) if body else {} - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/pay", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -535,13 +582,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_id = inputs["invoice_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoices/{invoice_id}/void", method="POST", headers=headers, ) - return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -574,7 +624,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="GET", headers=headers, @@ -605,13 +656,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_item_id = inputs["invoice_item_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="GET", headers=headers, ) - return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -645,14 +699,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -683,14 +740,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"invoice_item": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -705,7 +765,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): invoice_item_id = inputs["invoice_item_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/invoiceitems/{invoice_item_id}", method="DELETE", headers=headers, @@ -753,7 +814,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="GET", headers=headers, @@ -784,13 +846,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): product_id = inputs["product_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", method="GET", headers=headers, ) - return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -825,14 +890,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -870,14 +938,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/products/{product_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"product": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -916,7 +987,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="GET", headers=headers, @@ -947,13 +1019,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): price_id = inputs["price_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="GET", headers=headers, ) - return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"price": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -998,14 +1073,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"price": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1033,14 +1111,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/prices/{price_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"price": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1074,14 +1155,25 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: params["created[lte]"] = inputs.get("created_lte") - if "current_period_start_gte" in inputs and inputs["current_period_start_gte"]: - params["current_period_start[gte]"] = inputs.get("current_period_start_gte") - if "current_period_start_lte" in inputs and inputs["current_period_start_lte"]: - params["current_period_start[lte]"] = inputs.get("current_period_start_lte") + if ( + "current_period_start_gte" in inputs + and inputs["current_period_start_gte"] + ): + params["current_period_start[gte]"] = inputs.get( + "current_period_start_gte" + ) + if ( + "current_period_start_lte" in inputs + and inputs["current_period_start_lte"] + ): + params["current_period_start[lte]"] = inputs.get( + "current_period_start_lte" + ) headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="GET", headers=headers, @@ -1112,13 +1204,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): subscription_id = inputs["subscription_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="GET", headers=headers, ) - return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1143,7 +1238,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["payment_behavior"] = inputs.get("payment_behavior") if "billing_cycle_anchor" in inputs and inputs["billing_cycle_anchor"]: body["billing_cycle_anchor"] = inputs.get("billing_cycle_anchor") - if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: + if ( + "cancel_at_period_end" in inputs + and inputs["cancel_at_period_end"] is not None + ): body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs.get("cancel_at") @@ -1163,14 +1261,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1192,7 +1293,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["default_payment_method"] = inputs.get("default_payment_method") if "payment_behavior" in inputs and inputs["payment_behavior"]: body["payment_behavior"] = inputs.get("payment_behavior") - if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: + if ( + "cancel_at_period_end" in inputs + and inputs["cancel_at_period_end"] is not None + ): body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs.get("cancel_at") @@ -1210,14 +1314,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1240,7 +1347,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body = {"cancel_at_period_end": True} form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="POST", headers=headers, @@ -1258,14 +1366,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): form_data = build_form_data(body) if body else {} - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/subscriptions/{subscription_id}", method="DELETE", headers=headers, data=form_data if form_data else None, ) - return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"subscription": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1297,7 +1408,8 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods", method="GET", headers=headers, @@ -1328,13 +1440,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): payment_method_id = inputs["payment_method_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}", method="GET", headers=headers, ) - return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1352,14 +1467,17 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers = get_common_headers() form_data = build_form_data(body) - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}/attach", method="POST", headers=headers, data=form_data, ) - return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) @@ -1374,13 +1492,16 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): payment_method_id = inputs["payment_method_id"] headers = get_common_headers() - response = await _fetch(context, + response = await _fetch( + context, f"{STRIPE_API_BASE_URL}/{API_VERSION}/payment_methods/{payment_method_id}/detach", method="POST", headers=headers, ) - return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) + return ActionResult( + data={"payment_method": response.data, "result": True}, cost_usd=0.0 + ) except Exception as e: return ActionError(message=str(e)) diff --git a/stripe/tests/conftest.py b/stripe/tests/conftest.py index 5b3aee61..143f0f95 100644 --- a/stripe/tests/conftest.py +++ b/stripe/tests/conftest.py @@ -36,15 +36,21 @@ def stripe_context(): if not api_key: pytest.skip("STRIPE_TEST_API_KEY not set — skipping integration tests") - async def real_fetch(url, *, method="GET", json=None, headers=None, params=None, data=None, **kwargs): + async def real_fetch( + url, *, method="GET", json=None, headers=None, params=None, data=None, **kwargs + ): merged = dict(headers or {}) merged["Authorization"] = f"Bearer {api_key}" async with aiohttp.ClientSession() as session: - async with session.request(method, url, headers=merged, params=params, data=data, json=json) as resp: + async with session.request( + method, url, headers=merged, params=params, data=data, json=json + ) as resp: text = await resp.text() body = _json.loads(text) if text.strip() else {} - return FetchResponse(status=resp.status, headers=dict(resp.headers), data=body) + return FetchResponse( + status=resp.status, headers=dict(resp.headers), data=body + ) ctx = MagicMock(name="ExecutionContext") ctx.fetch = AsyncMock(side_effect=real_fetch) diff --git a/stripe/tests/test_stripe_integration.py b/stripe/tests/test_stripe_integration.py index e6dc6beb..8806920d 100644 --- a/stripe/tests/test_stripe_integration.py +++ b/stripe/tests/test_stripe_integration.py @@ -22,7 +22,9 @@ class TestListCustomers: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action("list_customers", {"limit": 5}, stripe_context) + result = await stripe.execute_action( + "list_customers", {"limit": 5}, stripe_context + ) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -32,7 +34,9 @@ async def test_returns_list(self, stripe_context): class TestListInvoices: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action("list_invoices", {"limit": 5}, stripe_context) + result = await stripe.execute_action( + "list_invoices", {"limit": 5}, stripe_context + ) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -41,14 +45,18 @@ async def test_returns_list(self, stripe_context): class TestListProducts: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action("list_products", {"limit": 5}, stripe_context) + result = await stripe.execute_action( + "list_products", {"limit": 5}, stripe_context + ) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True assert "products" in data async def test_active_filter(self, stripe_context): - result = await stripe.execute_action("list_products", {"limit": 5, "active": True}, stripe_context) + result = await stripe.execute_action( + "list_products", {"limit": 5, "active": True}, stripe_context + ) data = result.result.data assert data["result"] is True for p in data["products"]: @@ -57,7 +65,9 @@ async def test_active_filter(self, stripe_context): class TestListPrices: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action("list_prices", {"limit": 5}, stripe_context) + result = await stripe.execute_action( + "list_prices", {"limit": 5}, stripe_context + ) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -66,7 +76,9 @@ async def test_returns_list(self, stripe_context): class TestListSubscriptions: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action("list_subscriptions", {"limit": 5}, stripe_context) + result = await stripe.execute_action( + "list_subscriptions", {"limit": 5}, stripe_context + ) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -94,7 +106,9 @@ async def test_full_lifecycle(self, stripe_context): assert customer_id.startswith("cus_") # Get - get = await stripe.execute_action("get_customer", {"customer_id": customer_id}, stripe_context) + get = await stripe.execute_action( + "get_customer", {"customer_id": customer_id}, stripe_context + ) assert get.result.data["customer"]["id"] == customer_id # Update @@ -106,7 +120,9 @@ async def test_full_lifecycle(self, stripe_context): assert update.result.data["result"] is True # Delete (cleanup) - delete = await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + delete = await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True @@ -137,17 +153,25 @@ async def test_full_lifecycle(self, stripe_context): price_id = price.result.data["price"]["id"] # Get price - get_price = await stripe.execute_action("get_price", {"price_id": price_id}, stripe_context) + get_price = await stripe.execute_action( + "get_price", {"price_id": price_id}, stripe_context + ) assert get_price.result.data["price"]["id"] == price_id # Get product - get_prod = await stripe.execute_action("get_product", {"product_id": product_id}, stripe_context) + get_prod = await stripe.execute_action( + "get_product", {"product_id": product_id}, stripe_context + ) assert get_prod.result.data["product"]["id"] == product_id # Update product upd_prod = await stripe.execute_action( "update_product", - {"product_id": product_id, "name": f"AH Updated Product {uid}", "description": "Updated via test"}, + { + "product_id": product_id, + "name": f"AH Updated Product {uid}", + "description": "Updated via test", + }, stripe_context, ) assert upd_prod.result.data["result"] is True @@ -189,7 +213,12 @@ async def test_full_lifecycle(self, stripe_context): # Create draft invoice inv = await stripe.execute_action( "create_invoice", - {"customer": customer_id, "collection_method": "send_invoice", "days_until_due": 30, "currency": "nzd"}, + { + "customer": customer_id, + "collection_method": "send_invoice", + "days_until_due": 30, + "currency": "nzd", + }, stripe_context, ) assert inv.result.data["result"] is True @@ -199,14 +228,21 @@ async def test_full_lifecycle(self, stripe_context): # Add invoice item item = await stripe.execute_action( "create_invoice_item", - {"customer": customer_id, "invoice": invoice_id, "unit_amount": 1000, "currency": "nzd"}, + { + "customer": customer_id, + "invoice": invoice_id, + "unit_amount": 1000, + "currency": "nzd", + }, stripe_context, ) assert item.result.data["result"] is True item_id = item.result.data["invoice_item"]["id"] # Get invoice item - get_item = await stripe.execute_action("get_invoice_item", {"invoice_item_id": item_id}, stripe_context) + get_item = await stripe.execute_action( + "get_invoice_item", {"invoice_item_id": item_id}, stripe_context + ) assert get_item.result.data["invoice_item"]["id"] == item_id # Update invoice item @@ -216,14 +252,20 @@ async def test_full_lifecycle(self, stripe_context): stripe_context, ) assert upd_item.result.data["result"] is True - assert upd_item.result.data["invoice_item"]["description"] == f"Updated item {uid}" + assert ( + upd_item.result.data["invoice_item"]["description"] == f"Updated item {uid}" + ) # List invoice items - list_items = await stripe.execute_action("list_invoice_items", {"invoice": invoice_id}, stripe_context) + list_items = await stripe.execute_action( + "list_invoice_items", {"invoice": invoice_id}, stripe_context + ) assert list_items.result.data["result"] is True # Get invoice - get_inv = await stripe.execute_action("get_invoice", {"invoice_id": invoice_id}, stripe_context) + get_inv = await stripe.execute_action( + "get_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert get_inv.result.data["invoice"]["id"] == invoice_id # Update invoice @@ -235,21 +277,29 @@ async def test_full_lifecycle(self, stripe_context): assert upd_inv.result.data["result"] is True # Finalize invoice - fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) + fin = await stripe.execute_action( + "finalize_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert fin.result.data["result"] is True assert fin.result.data["invoice"]["status"] == "open" # Send invoice (safe in test mode — Stripe does not send real emails) - send = await stripe.execute_action("send_invoice", {"invoice_id": invoice_id}, stripe_context) + send = await stripe.execute_action( + "send_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert send.result.data["result"] is True # Void (cleanup) - void = await stripe.execute_action("void_invoice", {"invoice_id": invoice_id}, stripe_context) + void = await stripe.execute_action( + "void_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert void.result.data["result"] is True assert void.result.data["invoice"]["status"] == "void" # Cleanup customer - await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) @pytest.mark.destructive @@ -268,17 +318,25 @@ async def test_delete_draft(self, stripe_context): inv = await stripe.execute_action( "create_invoice", - {"customer": customer_id, "collection_method": "send_invoice", "days_until_due": 30}, + { + "customer": customer_id, + "collection_method": "send_invoice", + "days_until_due": 30, + }, stripe_context, ) invoice_id = inv.result.data["invoice"]["id"] assert inv.result.data["invoice"]["status"] == "draft" - delete = await stripe.execute_action("delete_invoice", {"invoice_id": invoice_id}, stripe_context) + delete = await stripe.execute_action( + "delete_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True - await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) @pytest.mark.destructive @@ -298,7 +356,12 @@ async def test_standalone_item(self, stripe_context): # Create standalone invoice item (not attached to any invoice) item = await stripe.execute_action( "create_invoice_item", - {"customer": customer_id, "unit_amount": 500, "currency": "nzd", "description": "Standalone item"}, + { + "customer": customer_id, + "unit_amount": 500, + "currency": "nzd", + "description": "Standalone item", + }, stripe_context, ) assert item.result.data["result"] is True @@ -313,11 +376,15 @@ async def test_standalone_item(self, stripe_context): assert upd.result.data["result"] is True # Delete item (only works on pending/unattached items) - delete = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": item_id}, stripe_context) + delete = await stripe.execute_action( + "delete_invoice_item", {"invoice_item_id": item_id}, stripe_context + ) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True - await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) @pytest.mark.destructive @@ -328,12 +395,19 @@ async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) # Create product + price - prod = await stripe.execute_action("create_product", {"name": f"AH Sub Product {uid}"}, stripe_context) + prod = await stripe.execute_action( + "create_product", {"name": f"AH Sub Product {uid}"}, stripe_context + ) product_id = prod.result.data["product"]["id"] price = await stripe.execute_action( "create_price", - {"product": product_id, "currency": "usd", "unit_amount": 500, "recurring": {"interval": "month"}}, + { + "product": product_id, + "currency": "usd", + "unit_amount": 500, + "recurring": {"interval": "month"}, + }, stripe_context, ) price_id = price.result.data["price"]["id"] @@ -362,7 +436,9 @@ async def test_full_lifecycle(self, stripe_context): subscription_id = sub.result.data["subscription"]["id"] # Get subscription - get_sub = await stripe.execute_action("get_subscription", {"subscription_id": subscription_id}, stripe_context) + get_sub = await stripe.execute_action( + "get_subscription", {"subscription_id": subscription_id}, stripe_context + ) assert get_sub.result.data["subscription"]["id"] == subscription_id # Update subscription @@ -376,17 +452,30 @@ async def test_full_lifecycle(self, stripe_context): # Cancel subscription (cleanup) cancel = await stripe.execute_action( "cancel_subscription", - {"subscription_id": subscription_id, "invoice_now": False, "prorate": False}, + { + "subscription_id": subscription_id, + "invoice_now": False, + "prorate": False, + }, stripe_context, ) assert cancel.result.data["result"] is True - assert cancel.result.data["subscription"]["status"] in ("canceled", "incomplete_expired") + assert cancel.result.data["subscription"]["status"] in ( + "canceled", + "incomplete_expired", + ) # Cleanup customer - await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) # Deactivate product - await stripe.execute_action("update_product", {"product_id": product_id, "active": False}, stripe_context) + await stripe.execute_action( + "update_product", + {"product_id": product_id, "active": False}, + stripe_context, + ) @pytest.mark.destructive @@ -446,12 +535,19 @@ async def test_full_lifecycle(self, stripe_context): item = await stripe.execute_action( "create_invoice_item", - {"customer": customer_id, "invoice": invoice_id, "unit_amount": 100, "currency": "usd"}, + { + "customer": customer_id, + "invoice": invoice_id, + "unit_amount": 100, + "currency": "usd", + }, stripe_context, ) assert item.result.data["result"] is True - fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) + fin = await stripe.execute_action( + "finalize_invoice", {"invoice_id": invoice_id}, stripe_context + ) assert fin.result.data["result"] is True assert fin.result.data["invoice"]["status"] == "open" @@ -473,4 +569,6 @@ async def test_full_lifecycle(self, stripe_context): assert detach.result.data["payment_method"]["customer"] is None # Cleanup customer - await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) + await stripe.execute_action( + "delete_customer", {"customer_id": customer_id}, stripe_context + ) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index 0bec80a9..0532f9f5 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -55,7 +55,10 @@ def ctx(): mock = MagicMock(name="ExecutionContext") mock.fetch = AsyncMock(return_value=FetchResponse(status=200, headers={}, data={})) - mock.auth = {"auth_type": "PlatformOauth2", "credentials": {"access_token": "sk_test_fake"}} # nosec B105 + mock.auth = { + "auth_type": "PlatformOauth2", + "credentials": {"access_token": "sk_test_fake"}, + } # nosec B105 return mock @@ -64,7 +67,9 @@ def ctx(): class TestListCustomers: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_CUSTOMER]}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_CUSTOMER]} + ) result = await stripe.execute_action("list_customers", {"limit": 5}, ctx) assert result.type == ResultType.ACTION assert result.result.data["result"] is True @@ -87,7 +92,9 @@ async def test_exception_returns_action_error(self, ctx): class TestGetCustomer: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) - result = await stripe.execute_action("get_customer", {"customer_id": "cus_test123"}, ctx) + result = await stripe.execute_action( + "get_customer", {"customer_id": "cus_test123"}, ctx + ) assert result.type == ResultType.ACTION assert result.result.data["result"] is True assert result.result.data["customer"]["id"] == "cus_test123" @@ -117,8 +124,12 @@ async def test_uses_post(self, ctx): class TestDeleteCustomer: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {"id": "cus_test123", "deleted": True}) - result = await stripe.execute_action("delete_customer", {"customer_id": "cus_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {"id": "cus_test123", "deleted": True} + ) + result = await stripe.execute_action( + "delete_customer", {"customer_id": "cus_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -128,7 +139,9 @@ async def test_success(self, ctx): class TestListInvoices: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_INVOICE]}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_INVOICE]} + ) result = await stripe.execute_action("list_invoices", {"limit": 5}, ctx) assert result.result.data["result"] is True assert len(result.result.data["invoices"]) == 1 @@ -143,15 +156,21 @@ async def test_status_filter(self, ctx): class TestGetInvoice: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) - result = await stripe.execute_action("get_invoice", {"invoice_id": "in_test123"}, ctx) + result = await stripe.execute_action( + "get_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["invoice"]["id"] == "in_test123" class TestDeleteInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {"id": "in_test123", "deleted": True}) - result = await stripe.execute_action("delete_invoice", {"invoice_id": "in_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {"id": "in_test123", "deleted": True} + ) + result = await stripe.execute_action( + "delete_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -161,7 +180,9 @@ async def test_success(self, ctx): class TestListProducts: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRODUCT]}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRODUCT]} + ) result = await stripe.execute_action("list_products", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["products"]) == 1 @@ -176,7 +197,9 @@ async def test_active_filter(self, ctx): class TestGetProduct: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRODUCT) - result = await stripe.execute_action("get_product", {"product_id": "prod_test123"}, ctx) + result = await stripe.execute_action( + "get_product", {"product_id": "prod_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["product"]["id"] == "prod_test123" @@ -186,7 +209,9 @@ async def test_success(self, ctx): class TestListPrices: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRICE]}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRICE]} + ) result = await stripe.execute_action("list_prices", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["prices"]) == 1 @@ -195,7 +220,9 @@ async def test_success(self, ctx): class TestGetPrice: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRICE) - result = await stripe.execute_action("get_price", {"price_id": "price_test123"}, ctx) + result = await stripe.execute_action( + "get_price", {"price_id": "price_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["price"]["id"] == "price_test123" @@ -212,7 +239,9 @@ async def test_success(self, ctx): async def test_invoice_filter(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) - await stripe.execute_action("list_invoice_items", {"invoice": "in_test123"}, ctx) + await stripe.execute_action( + "list_invoice_items", {"invoice": "in_test123"}, ctx + ) params = ctx.fetch.call_args.kwargs.get("params", {}) assert params.get("invoice") == "in_test123" @@ -221,7 +250,9 @@ class TestGetInvoiceItem: async def test_success(self, ctx): item = {"id": "ii_test123", "object": "invoiceitem", "amount": 500} ctx.fetch.return_value = FetchResponse(200, {}, item) - result = await stripe.execute_action("get_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) + result = await stripe.execute_action( + "get_invoice_item", {"invoice_item_id": "ii_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["invoice_item"]["id"] == "ii_test123" @@ -249,8 +280,12 @@ async def test_uses_post(self, ctx): class TestDeleteInvoiceItem: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {"id": "ii_test123", "deleted": True}) - result = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {"id": "ii_test123", "deleted": True} + ) + result = await stripe.execute_action( + "delete_invoice_item", {"invoice_item_id": "ii_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -260,8 +295,12 @@ async def test_success(self, ctx): class TestFinalizeInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) - result = await stripe.execute_action("finalize_invoice", {"invoice_id": "in_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_INVOICE, "status": "open"} + ) + result = await stripe.execute_action( + "finalize_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["invoice"]["status"] == "open" @@ -274,8 +313,12 @@ async def test_url_contains_finalize(self, ctx): class TestVoidInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "void"}) - result = await stripe.execute_action("void_invoice", {"invoice_id": "in_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_INVOICE, "status": "void"} + ) + result = await stripe.execute_action( + "void_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True async def test_url_contains_void(self, ctx): @@ -286,8 +329,12 @@ async def test_url_contains_void(self, ctx): class TestSendInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) - result = await stripe.execute_action("send_invoice", {"invoice_id": "in_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_INVOICE, "status": "open"} + ) + result = await stripe.execute_action( + "send_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True async def test_url_contains_send(self, ctx): @@ -298,8 +345,12 @@ async def test_url_contains_send(self, ctx): class TestPayInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "paid"}) - result = await stripe.execute_action("pay_invoice", {"invoice_id": "in_test123"}, ctx) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_INVOICE, "status": "paid"} + ) + result = await stripe.execute_action( + "pay_invoice", {"invoice_id": "in_test123"}, ctx + ) assert result.result.data["result"] is True async def test_url_contains_pay(self, ctx): @@ -313,7 +364,9 @@ async def test_url_contains_pay(self, ctx): class TestListSubscriptions: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_SUBSCRIPTION]}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_SUBSCRIPTION]} + ) result = await stripe.execute_action("list_subscriptions", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["subscriptions"]) == 1 @@ -322,7 +375,9 @@ async def test_success(self, ctx): class TestGetSubscription: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) - result = await stripe.execute_action("get_subscription", {"subscription_id": "sub_test123"}, ctx) + result = await stripe.execute_action( + "get_subscription", {"subscription_id": "sub_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["subscription"]["id"] == "sub_test123" @@ -370,7 +425,9 @@ async def test_url_contains_subscription_id(self, ctx): class TestCancelSubscription: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_SUBSCRIPTION, "status": "canceled"}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {**SAMPLE_SUBSCRIPTION, "status": "canceled"} + ) result = await stripe.execute_action( "cancel_subscription", {"subscription_id": "sub_test123"}, @@ -399,7 +456,9 @@ class TestGetPaymentMethod: async def test_success(self, ctx): pm = {"id": "pm_test123", "object": "payment_method", "type": "card"} ctx.fetch.return_value = FetchResponse(200, {}, pm) - result = await stripe.execute_action("get_payment_method", {"payment_method_id": "pm_test123"}, ctx) + result = await stripe.execute_action( + "get_payment_method", {"payment_method_id": "pm_test123"}, ctx + ) assert result.result.data["result"] is True assert result.result.data["payment_method"]["id"] == "pm_test123" @@ -430,12 +489,16 @@ class TestDetachPaymentMethod: async def test_success(self, ctx): pm = {"id": "pm_test123", "object": "payment_method", "customer": None} ctx.fetch.return_value = FetchResponse(200, {}, pm) - result = await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_test123"}, ctx) + result = await stripe.execute_action( + "detach_payment_method", {"payment_method_id": "pm_test123"}, ctx + ) assert result.result.data["result"] is True async def test_url_contains_detach(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, {}) - await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_abc"}, ctx) + await stripe.execute_action( + "detach_payment_method", {"payment_method_id": "pm_abc"}, ctx + ) assert "detach" in ctx.fetch.call_args.args[0] @@ -492,7 +555,9 @@ async def test_falls_back_to_stripe_account_on_exception(self, ctx): assert result.result.username == "Stripe Account" async def test_calls_account_endpoint(self, ctx): - ctx.fetch.return_value = FetchResponse(200, {}, {"id": "acct_test123", "email": "x@x.com"}) + ctx.fetch.return_value = FetchResponse( + 200, {}, {"id": "acct_test123", "email": "x@x.com"} + ) await stripe.get_connected_account(ctx) assert "/account" in ctx.fetch.call_args.args[0] assert ctx.fetch.call_args.kwargs["method"] == "GET" From d43cc1d6a23bc2bb68fa491a5db1ad73be5d23e5 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:57:43 +1200 Subject: [PATCH 15/18] fix(stripe): move nosec comment to flagged line, re-run ruff format --- stripe/tests/test_stripe_unit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index 0532f9f5..8accb308 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -57,8 +57,8 @@ def ctx(): mock.fetch = AsyncMock(return_value=FetchResponse(status=200, headers={}, data={})) mock.auth = { "auth_type": "PlatformOauth2", - "credentials": {"access_token": "sk_test_fake"}, - } # nosec B105 + "credentials": {"access_token": "sk_test_fake"}, # nosec B105 + } return mock From 6728a6c0ff30ed3dd38b816aa6ad065eaa6fb46c Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:59:21 +1200 Subject: [PATCH 16/18] fix(stripe): add ruff.toml with line-length=120, reformat to match CI --- stripe/ruff.toml | 1 + stripe/stripe.py | 143 ++++++------------------ stripe/tests/conftest.py | 12 +- stripe/tests/test_stripe_integration.py | 108 +++++------------- stripe/tests/test_stripe_unit.py | 124 +++++--------------- 5 files changed, 96 insertions(+), 292 deletions(-) create mode 100644 stripe/ruff.toml diff --git a/stripe/ruff.toml b/stripe/ruff.toml new file mode 100644 index 00000000..f11cf635 --- /dev/null +++ b/stripe/ruff.toml @@ -0,0 +1 @@ +line-length = 120 diff --git a/stripe/stripe.py b/stripe/stripe.py index 0bed10a4..5bd22a54 100644 --- a/stripe/stripe.py +++ b/stripe/stripe.py @@ -47,9 +47,7 @@ async def _fetch( params=None, ): """Wrap context.fetch and raise StripeAPIError with Stripe's error message on non-2xx responses.""" - response = await context.fetch( - url, method=method, headers=headers, data=data, params=params - ) + response = await context.fetch(url, method=method, headers=headers, data=data, params=params) if response.status >= 400: err = (response.data or {}).get("error") or {} msg = err.get("message") or f"Stripe API error (HTTP {response.status})" @@ -104,12 +102,7 @@ async def get_account_info(self, context: ExecutionContext) -> ConnectedAccountI # business_profile is null for unconfigured accounts, so guard against None before .get() business_profile = data.get("business_profile") or {} email = data.get("email") or business_profile.get("support_email", "") - name = ( - business_profile.get("name") - or data.get("display_name") - or email - or "Stripe Account" - ) + name = business_profile.get("name") or data.get("display_name") or email or "Stripe Account" return ConnectedAccountInfo(username=name, user_id=data.get("id")) except Exception: return ConnectedAccountInfo(username="Stripe Account") @@ -181,9 +174,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"customer": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -222,9 +213,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"customer": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -264,9 +253,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"customer": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"customer": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -369,9 +356,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -410,9 +395,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -450,9 +433,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -510,9 +491,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -534,9 +513,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -565,9 +542,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -589,9 +564,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -663,9 +636,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"invoice_item": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -707,9 +678,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice_item": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -748,9 +717,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"invoice_item": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"invoice_item": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -853,9 +820,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"product": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -898,9 +863,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"product": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -946,9 +909,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"product": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"product": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1026,9 +987,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"price": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1081,9 +1040,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"price": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1119,9 +1076,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"price": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"price": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1155,20 +1110,10 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): params["created[gte]"] = inputs.get("created_gte") if "created_lte" in inputs and inputs["created_lte"]: params["created[lte]"] = inputs.get("created_lte") - if ( - "current_period_start_gte" in inputs - and inputs["current_period_start_gte"] - ): - params["current_period_start[gte]"] = inputs.get( - "current_period_start_gte" - ) - if ( - "current_period_start_lte" in inputs - and inputs["current_period_start_lte"] - ): - params["current_period_start[lte]"] = inputs.get( - "current_period_start_lte" - ) + if "current_period_start_gte" in inputs and inputs["current_period_start_gte"]: + params["current_period_start[gte]"] = inputs.get("current_period_start_gte") + if "current_period_start_lte" in inputs and inputs["current_period_start_lte"]: + params["current_period_start[lte]"] = inputs.get("current_period_start_lte") headers = get_common_headers() @@ -1211,9 +1156,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"subscription": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1238,10 +1181,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["payment_behavior"] = inputs.get("payment_behavior") if "billing_cycle_anchor" in inputs and inputs["billing_cycle_anchor"]: body["billing_cycle_anchor"] = inputs.get("billing_cycle_anchor") - if ( - "cancel_at_period_end" in inputs - and inputs["cancel_at_period_end"] is not None - ): + if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs.get("cancel_at") @@ -1269,9 +1209,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"subscription": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1293,10 +1231,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): body["default_payment_method"] = inputs.get("default_payment_method") if "payment_behavior" in inputs and inputs["payment_behavior"]: body["payment_behavior"] = inputs.get("payment_behavior") - if ( - "cancel_at_period_end" in inputs - and inputs["cancel_at_period_end"] is not None - ): + if "cancel_at_period_end" in inputs and inputs["cancel_at_period_end"] is not None: body["cancel_at_period_end"] = inputs.get("cancel_at_period_end") if "cancel_at" in inputs and inputs["cancel_at"]: body["cancel_at"] = inputs.get("cancel_at") @@ -1322,9 +1257,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"subscription": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1374,9 +1307,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data if form_data else None, ) - return ActionResult( - data={"subscription": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"subscription": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1447,9 +1378,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"payment_method": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1475,9 +1404,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): data=form_data, ) - return ActionResult( - data={"payment_method": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) @@ -1499,9 +1426,7 @@ async def execute(self, inputs: Dict[str, Any], context: ExecutionContext): headers=headers, ) - return ActionResult( - data={"payment_method": response.data, "result": True}, cost_usd=0.0 - ) + return ActionResult(data={"payment_method": response.data, "result": True}, cost_usd=0.0) except Exception as e: return ActionError(message=str(e)) diff --git a/stripe/tests/conftest.py b/stripe/tests/conftest.py index 143f0f95..5b3aee61 100644 --- a/stripe/tests/conftest.py +++ b/stripe/tests/conftest.py @@ -36,21 +36,15 @@ def stripe_context(): if not api_key: pytest.skip("STRIPE_TEST_API_KEY not set — skipping integration tests") - async def real_fetch( - url, *, method="GET", json=None, headers=None, params=None, data=None, **kwargs - ): + async def real_fetch(url, *, method="GET", json=None, headers=None, params=None, data=None, **kwargs): merged = dict(headers or {}) merged["Authorization"] = f"Bearer {api_key}" async with aiohttp.ClientSession() as session: - async with session.request( - method, url, headers=merged, params=params, data=data, json=json - ) as resp: + async with session.request(method, url, headers=merged, params=params, data=data, json=json) as resp: text = await resp.text() body = _json.loads(text) if text.strip() else {} - return FetchResponse( - status=resp.status, headers=dict(resp.headers), data=body - ) + return FetchResponse(status=resp.status, headers=dict(resp.headers), data=body) ctx = MagicMock(name="ExecutionContext") ctx.fetch = AsyncMock(side_effect=real_fetch) diff --git a/stripe/tests/test_stripe_integration.py b/stripe/tests/test_stripe_integration.py index 8806920d..33c78604 100644 --- a/stripe/tests/test_stripe_integration.py +++ b/stripe/tests/test_stripe_integration.py @@ -22,9 +22,7 @@ class TestListCustomers: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action( - "list_customers", {"limit": 5}, stripe_context - ) + result = await stripe.execute_action("list_customers", {"limit": 5}, stripe_context) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -34,9 +32,7 @@ async def test_returns_list(self, stripe_context): class TestListInvoices: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action( - "list_invoices", {"limit": 5}, stripe_context - ) + result = await stripe.execute_action("list_invoices", {"limit": 5}, stripe_context) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -45,18 +41,14 @@ async def test_returns_list(self, stripe_context): class TestListProducts: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action( - "list_products", {"limit": 5}, stripe_context - ) + result = await stripe.execute_action("list_products", {"limit": 5}, stripe_context) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True assert "products" in data async def test_active_filter(self, stripe_context): - result = await stripe.execute_action( - "list_products", {"limit": 5, "active": True}, stripe_context - ) + result = await stripe.execute_action("list_products", {"limit": 5, "active": True}, stripe_context) data = result.result.data assert data["result"] is True for p in data["products"]: @@ -65,9 +57,7 @@ async def test_active_filter(self, stripe_context): class TestListPrices: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action( - "list_prices", {"limit": 5}, stripe_context - ) + result = await stripe.execute_action("list_prices", {"limit": 5}, stripe_context) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -76,9 +66,7 @@ async def test_returns_list(self, stripe_context): class TestListSubscriptions: async def test_returns_list(self, stripe_context): - result = await stripe.execute_action( - "list_subscriptions", {"limit": 5}, stripe_context - ) + result = await stripe.execute_action("list_subscriptions", {"limit": 5}, stripe_context) assert result.type == ResultType.ACTION data = result.result.data assert data["result"] is True @@ -106,9 +94,7 @@ async def test_full_lifecycle(self, stripe_context): assert customer_id.startswith("cus_") # Get - get = await stripe.execute_action( - "get_customer", {"customer_id": customer_id}, stripe_context - ) + get = await stripe.execute_action("get_customer", {"customer_id": customer_id}, stripe_context) assert get.result.data["customer"]["id"] == customer_id # Update @@ -120,9 +106,7 @@ async def test_full_lifecycle(self, stripe_context): assert update.result.data["result"] is True # Delete (cleanup) - delete = await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + delete = await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True @@ -153,15 +137,11 @@ async def test_full_lifecycle(self, stripe_context): price_id = price.result.data["price"]["id"] # Get price - get_price = await stripe.execute_action( - "get_price", {"price_id": price_id}, stripe_context - ) + get_price = await stripe.execute_action("get_price", {"price_id": price_id}, stripe_context) assert get_price.result.data["price"]["id"] == price_id # Get product - get_prod = await stripe.execute_action( - "get_product", {"product_id": product_id}, stripe_context - ) + get_prod = await stripe.execute_action("get_product", {"product_id": product_id}, stripe_context) assert get_prod.result.data["product"]["id"] == product_id # Update product @@ -240,9 +220,7 @@ async def test_full_lifecycle(self, stripe_context): item_id = item.result.data["invoice_item"]["id"] # Get invoice item - get_item = await stripe.execute_action( - "get_invoice_item", {"invoice_item_id": item_id}, stripe_context - ) + get_item = await stripe.execute_action("get_invoice_item", {"invoice_item_id": item_id}, stripe_context) assert get_item.result.data["invoice_item"]["id"] == item_id # Update invoice item @@ -252,20 +230,14 @@ async def test_full_lifecycle(self, stripe_context): stripe_context, ) assert upd_item.result.data["result"] is True - assert ( - upd_item.result.data["invoice_item"]["description"] == f"Updated item {uid}" - ) + assert upd_item.result.data["invoice_item"]["description"] == f"Updated item {uid}" # List invoice items - list_items = await stripe.execute_action( - "list_invoice_items", {"invoice": invoice_id}, stripe_context - ) + list_items = await stripe.execute_action("list_invoice_items", {"invoice": invoice_id}, stripe_context) assert list_items.result.data["result"] is True # Get invoice - get_inv = await stripe.execute_action( - "get_invoice", {"invoice_id": invoice_id}, stripe_context - ) + get_inv = await stripe.execute_action("get_invoice", {"invoice_id": invoice_id}, stripe_context) assert get_inv.result.data["invoice"]["id"] == invoice_id # Update invoice @@ -277,29 +249,21 @@ async def test_full_lifecycle(self, stripe_context): assert upd_inv.result.data["result"] is True # Finalize invoice - fin = await stripe.execute_action( - "finalize_invoice", {"invoice_id": invoice_id}, stripe_context - ) + fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) assert fin.result.data["result"] is True assert fin.result.data["invoice"]["status"] == "open" # Send invoice (safe in test mode — Stripe does not send real emails) - send = await stripe.execute_action( - "send_invoice", {"invoice_id": invoice_id}, stripe_context - ) + send = await stripe.execute_action("send_invoice", {"invoice_id": invoice_id}, stripe_context) assert send.result.data["result"] is True # Void (cleanup) - void = await stripe.execute_action( - "void_invoice", {"invoice_id": invoice_id}, stripe_context - ) + void = await stripe.execute_action("void_invoice", {"invoice_id": invoice_id}, stripe_context) assert void.result.data["result"] is True assert void.result.data["invoice"]["status"] == "void" # Cleanup customer - await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) @pytest.mark.destructive @@ -328,15 +292,11 @@ async def test_delete_draft(self, stripe_context): invoice_id = inv.result.data["invoice"]["id"] assert inv.result.data["invoice"]["status"] == "draft" - delete = await stripe.execute_action( - "delete_invoice", {"invoice_id": invoice_id}, stripe_context - ) + delete = await stripe.execute_action("delete_invoice", {"invoice_id": invoice_id}, stripe_context) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True - await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) @pytest.mark.destructive @@ -376,15 +336,11 @@ async def test_standalone_item(self, stripe_context): assert upd.result.data["result"] is True # Delete item (only works on pending/unattached items) - delete = await stripe.execute_action( - "delete_invoice_item", {"invoice_item_id": item_id}, stripe_context - ) + delete = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": item_id}, stripe_context) assert delete.result.data["result"] is True assert delete.result.data["deleted"] is True - await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) @pytest.mark.destructive @@ -395,9 +351,7 @@ async def test_full_lifecycle(self, stripe_context): uid = int(time.time()) # Create product + price - prod = await stripe.execute_action( - "create_product", {"name": f"AH Sub Product {uid}"}, stripe_context - ) + prod = await stripe.execute_action("create_product", {"name": f"AH Sub Product {uid}"}, stripe_context) product_id = prod.result.data["product"]["id"] price = await stripe.execute_action( @@ -436,9 +390,7 @@ async def test_full_lifecycle(self, stripe_context): subscription_id = sub.result.data["subscription"]["id"] # Get subscription - get_sub = await stripe.execute_action( - "get_subscription", {"subscription_id": subscription_id}, stripe_context - ) + get_sub = await stripe.execute_action("get_subscription", {"subscription_id": subscription_id}, stripe_context) assert get_sub.result.data["subscription"]["id"] == subscription_id # Update subscription @@ -466,9 +418,7 @@ async def test_full_lifecycle(self, stripe_context): ) # Cleanup customer - await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) # Deactivate product await stripe.execute_action( @@ -545,9 +495,7 @@ async def test_full_lifecycle(self, stripe_context): ) assert item.result.data["result"] is True - fin = await stripe.execute_action( - "finalize_invoice", {"invoice_id": invoice_id}, stripe_context - ) + fin = await stripe.execute_action("finalize_invoice", {"invoice_id": invoice_id}, stripe_context) assert fin.result.data["result"] is True assert fin.result.data["invoice"]["status"] == "open" @@ -569,6 +517,4 @@ async def test_full_lifecycle(self, stripe_context): assert detach.result.data["payment_method"]["customer"] is None # Cleanup customer - await stripe.execute_action( - "delete_customer", {"customer_id": customer_id}, stripe_context - ) + await stripe.execute_action("delete_customer", {"customer_id": customer_id}, stripe_context) diff --git a/stripe/tests/test_stripe_unit.py b/stripe/tests/test_stripe_unit.py index 8accb308..4f4cc1d2 100644 --- a/stripe/tests/test_stripe_unit.py +++ b/stripe/tests/test_stripe_unit.py @@ -67,9 +67,7 @@ def ctx(): class TestListCustomers: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_CUSTOMER]} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_CUSTOMER]}) result = await stripe.execute_action("list_customers", {"limit": 5}, ctx) assert result.type == ResultType.ACTION assert result.result.data["result"] is True @@ -92,9 +90,7 @@ async def test_exception_returns_action_error(self, ctx): class TestGetCustomer: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_CUSTOMER) - result = await stripe.execute_action( - "get_customer", {"customer_id": "cus_test123"}, ctx - ) + result = await stripe.execute_action("get_customer", {"customer_id": "cus_test123"}, ctx) assert result.type == ResultType.ACTION assert result.result.data["result"] is True assert result.result.data["customer"]["id"] == "cus_test123" @@ -124,12 +120,8 @@ async def test_uses_post(self, ctx): class TestDeleteCustomer: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {"id": "cus_test123", "deleted": True} - ) - result = await stripe.execute_action( - "delete_customer", {"customer_id": "cus_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "cus_test123", "deleted": True}) + result = await stripe.execute_action("delete_customer", {"customer_id": "cus_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -139,9 +131,7 @@ async def test_success(self, ctx): class TestListInvoices: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_INVOICE]} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_INVOICE]}) result = await stripe.execute_action("list_invoices", {"limit": 5}, ctx) assert result.result.data["result"] is True assert len(result.result.data["invoices"]) == 1 @@ -156,21 +146,15 @@ async def test_status_filter(self, ctx): class TestGetInvoice: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_INVOICE) - result = await stripe.execute_action( - "get_invoice", {"invoice_id": "in_test123"}, ctx - ) + result = await stripe.execute_action("get_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["invoice"]["id"] == "in_test123" class TestDeleteInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {"id": "in_test123", "deleted": True} - ) - result = await stripe.execute_action( - "delete_invoice", {"invoice_id": "in_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "in_test123", "deleted": True}) + result = await stripe.execute_action("delete_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -180,9 +164,7 @@ async def test_success(self, ctx): class TestListProducts: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRODUCT]} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRODUCT]}) result = await stripe.execute_action("list_products", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["products"]) == 1 @@ -197,9 +179,7 @@ async def test_active_filter(self, ctx): class TestGetProduct: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRODUCT) - result = await stripe.execute_action( - "get_product", {"product_id": "prod_test123"}, ctx - ) + result = await stripe.execute_action("get_product", {"product_id": "prod_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["product"]["id"] == "prod_test123" @@ -209,9 +189,7 @@ async def test_success(self, ctx): class TestListPrices: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRICE]} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_PRICE]}) result = await stripe.execute_action("list_prices", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["prices"]) == 1 @@ -220,9 +198,7 @@ async def test_success(self, ctx): class TestGetPrice: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_PRICE) - result = await stripe.execute_action( - "get_price", {"price_id": "price_test123"}, ctx - ) + result = await stripe.execute_action("get_price", {"price_id": "price_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["price"]["id"] == "price_test123" @@ -239,9 +215,7 @@ async def test_success(self, ctx): async def test_invoice_filter(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_LIST) - await stripe.execute_action( - "list_invoice_items", {"invoice": "in_test123"}, ctx - ) + await stripe.execute_action("list_invoice_items", {"invoice": "in_test123"}, ctx) params = ctx.fetch.call_args.kwargs.get("params", {}) assert params.get("invoice") == "in_test123" @@ -250,9 +224,7 @@ class TestGetInvoiceItem: async def test_success(self, ctx): item = {"id": "ii_test123", "object": "invoiceitem", "amount": 500} ctx.fetch.return_value = FetchResponse(200, {}, item) - result = await stripe.execute_action( - "get_invoice_item", {"invoice_item_id": "ii_test123"}, ctx - ) + result = await stripe.execute_action("get_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["invoice_item"]["id"] == "ii_test123" @@ -280,12 +252,8 @@ async def test_uses_post(self, ctx): class TestDeleteInvoiceItem: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {"id": "ii_test123", "deleted": True} - ) - result = await stripe.execute_action( - "delete_invoice_item", {"invoice_item_id": "ii_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "ii_test123", "deleted": True}) + result = await stripe.execute_action("delete_invoice_item", {"invoice_item_id": "ii_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["deleted"] is True @@ -295,12 +263,8 @@ async def test_success(self, ctx): class TestFinalizeInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_INVOICE, "status": "open"} - ) - result = await stripe.execute_action( - "finalize_invoice", {"invoice_id": "in_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) + result = await stripe.execute_action("finalize_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["invoice"]["status"] == "open" @@ -313,12 +277,8 @@ async def test_url_contains_finalize(self, ctx): class TestVoidInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_INVOICE, "status": "void"} - ) - result = await stripe.execute_action( - "void_invoice", {"invoice_id": "in_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "void"}) + result = await stripe.execute_action("void_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True async def test_url_contains_void(self, ctx): @@ -329,12 +289,8 @@ async def test_url_contains_void(self, ctx): class TestSendInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_INVOICE, "status": "open"} - ) - result = await stripe.execute_action( - "send_invoice", {"invoice_id": "in_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "open"}) + result = await stripe.execute_action("send_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True async def test_url_contains_send(self, ctx): @@ -345,12 +301,8 @@ async def test_url_contains_send(self, ctx): class TestPayInvoice: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_INVOICE, "status": "paid"} - ) - result = await stripe.execute_action( - "pay_invoice", {"invoice_id": "in_test123"}, ctx - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_INVOICE, "status": "paid"}) + result = await stripe.execute_action("pay_invoice", {"invoice_id": "in_test123"}, ctx) assert result.result.data["result"] is True async def test_url_contains_pay(self, ctx): @@ -364,9 +316,7 @@ async def test_url_contains_pay(self, ctx): class TestListSubscriptions: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_LIST, "data": [SAMPLE_SUBSCRIPTION]} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_LIST, "data": [SAMPLE_SUBSCRIPTION]}) result = await stripe.execute_action("list_subscriptions", {"limit": 3}, ctx) assert result.result.data["result"] is True assert len(result.result.data["subscriptions"]) == 1 @@ -375,9 +325,7 @@ async def test_success(self, ctx): class TestGetSubscription: async def test_success(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, SAMPLE_SUBSCRIPTION) - result = await stripe.execute_action( - "get_subscription", {"subscription_id": "sub_test123"}, ctx - ) + result = await stripe.execute_action("get_subscription", {"subscription_id": "sub_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["subscription"]["id"] == "sub_test123" @@ -425,9 +373,7 @@ async def test_url_contains_subscription_id(self, ctx): class TestCancelSubscription: async def test_success(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {**SAMPLE_SUBSCRIPTION, "status": "canceled"} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {**SAMPLE_SUBSCRIPTION, "status": "canceled"}) result = await stripe.execute_action( "cancel_subscription", {"subscription_id": "sub_test123"}, @@ -456,9 +402,7 @@ class TestGetPaymentMethod: async def test_success(self, ctx): pm = {"id": "pm_test123", "object": "payment_method", "type": "card"} ctx.fetch.return_value = FetchResponse(200, {}, pm) - result = await stripe.execute_action( - "get_payment_method", {"payment_method_id": "pm_test123"}, ctx - ) + result = await stripe.execute_action("get_payment_method", {"payment_method_id": "pm_test123"}, ctx) assert result.result.data["result"] is True assert result.result.data["payment_method"]["id"] == "pm_test123" @@ -489,16 +433,12 @@ class TestDetachPaymentMethod: async def test_success(self, ctx): pm = {"id": "pm_test123", "object": "payment_method", "customer": None} ctx.fetch.return_value = FetchResponse(200, {}, pm) - result = await stripe.execute_action( - "detach_payment_method", {"payment_method_id": "pm_test123"}, ctx - ) + result = await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_test123"}, ctx) assert result.result.data["result"] is True async def test_url_contains_detach(self, ctx): ctx.fetch.return_value = FetchResponse(200, {}, {}) - await stripe.execute_action( - "detach_payment_method", {"payment_method_id": "pm_abc"}, ctx - ) + await stripe.execute_action("detach_payment_method", {"payment_method_id": "pm_abc"}, ctx) assert "detach" in ctx.fetch.call_args.args[0] @@ -555,9 +495,7 @@ async def test_falls_back_to_stripe_account_on_exception(self, ctx): assert result.result.username == "Stripe Account" async def test_calls_account_endpoint(self, ctx): - ctx.fetch.return_value = FetchResponse( - 200, {}, {"id": "acct_test123", "email": "x@x.com"} - ) + ctx.fetch.return_value = FetchResponse(200, {}, {"id": "acct_test123", "email": "x@x.com"}) await stripe.get_connected_account(ctx) assert "/account" in ctx.fetch.call_args.args[0] assert ctx.fetch.call_args.kwargs["method"] == "GET" From 2c20308097bc00b3202c268b2f13d5f8757e1540 Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 13:59:57 +1200 Subject: [PATCH 17/18] fix(stripe): replace custom ruff.toml with standard one from tooling --- stripe/ruff.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stripe/ruff.toml b/stripe/ruff.toml index f11cf635..a4e8b625 100644 --- a/stripe/ruff.toml +++ b/stripe/ruff.toml @@ -1 +1,9 @@ +target-version = "py313" line-length = 120 + +[lint] +select = ["E", "F", "W"] + +[lint.per-file-ignores] +"__init__.py" = ["F401"] +"**/tests/context.py" = ["F401", "E402"] From d9f45cb626f990a1cf04f8249bf4452ed4f5a70d Mon Sep 17 00:00:00 2001 From: Shubhank <72601061+Sagsgit@users.noreply.github.com> Date: Tue, 12 May 2026 14:00:12 +1200 Subject: [PATCH 18/18] fix(stripe): remove ruff.toml, tooling handles formatting config --- stripe/ruff.toml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 stripe/ruff.toml diff --git a/stripe/ruff.toml b/stripe/ruff.toml deleted file mode 100644 index a4e8b625..00000000 --- a/stripe/ruff.toml +++ /dev/null @@ -1,9 +0,0 @@ -target-version = "py313" -line-length = 120 - -[lint] -select = ["E", "F", "W"] - -[lint.per-file-ignores] -"__init__.py" = ["F401"] -"**/tests/context.py" = ["F401", "E402"]