1use std::sync::Arc;
2
3use anyhow::{Result, anyhow};
4use async_trait::async_trait;
5use collections::HashMap;
6use parking_lot::Mutex;
7use uuid::Uuid;
8
9use crate::stripe_client::{
10 CreateCustomerParams, StripeClient, StripeCreateMeterEventParams, StripeCustomer,
11 StripeCustomerId, StripeMeter, StripeMeterId, StripePrice, StripePriceId, StripeSubscription,
12 StripeSubscriptionId, UpdateSubscriptionParams,
13};
14
15#[derive(Debug, Clone)]
16pub struct StripeCreateMeterEventCall {
17 pub identifier: Arc<str>,
18 pub event_name: Arc<str>,
19 pub value: u64,
20 pub stripe_customer_id: StripeCustomerId,
21 pub timestamp: Option<i64>,
22}
23
24pub struct FakeStripeClient {
25 pub customers: Arc<Mutex<HashMap<StripeCustomerId, StripeCustomer>>>,
26 pub subscriptions: Arc<Mutex<HashMap<StripeSubscriptionId, StripeSubscription>>>,
27 pub update_subscription_calls:
28 Arc<Mutex<Vec<(StripeSubscriptionId, UpdateSubscriptionParams)>>>,
29 pub prices: Arc<Mutex<HashMap<StripePriceId, StripePrice>>>,
30 pub meters: Arc<Mutex<HashMap<StripeMeterId, StripeMeter>>>,
31 pub create_meter_event_calls: Arc<Mutex<Vec<StripeCreateMeterEventCall>>>,
32}
33
34impl FakeStripeClient {
35 pub fn new() -> Self {
36 Self {
37 customers: Arc::new(Mutex::new(HashMap::default())),
38 subscriptions: Arc::new(Mutex::new(HashMap::default())),
39 update_subscription_calls: Arc::new(Mutex::new(Vec::new())),
40 prices: Arc::new(Mutex::new(HashMap::default())),
41 meters: Arc::new(Mutex::new(HashMap::default())),
42 create_meter_event_calls: Arc::new(Mutex::new(Vec::new())),
43 }
44 }
45}
46
47#[async_trait]
48impl StripeClient for FakeStripeClient {
49 async fn list_customers_by_email(&self, email: &str) -> Result<Vec<StripeCustomer>> {
50 Ok(self
51 .customers
52 .lock()
53 .values()
54 .filter(|customer| customer.email.as_deref() == Some(email))
55 .cloned()
56 .collect())
57 }
58
59 async fn create_customer(&self, params: CreateCustomerParams<'_>) -> Result<StripeCustomer> {
60 let customer = StripeCustomer {
61 id: StripeCustomerId(format!("cus_{}", Uuid::new_v4()).into()),
62 email: params.email.map(|email| email.to_string()),
63 };
64
65 self.customers
66 .lock()
67 .insert(customer.id.clone(), customer.clone());
68
69 Ok(customer)
70 }
71
72 async fn get_subscription(
73 &self,
74 subscription_id: &StripeSubscriptionId,
75 ) -> Result<StripeSubscription> {
76 self.subscriptions
77 .lock()
78 .get(subscription_id)
79 .cloned()
80 .ok_or_else(|| anyhow!("no subscription found for {subscription_id:?}"))
81 }
82
83 async fn update_subscription(
84 &self,
85 subscription_id: &StripeSubscriptionId,
86 params: UpdateSubscriptionParams,
87 ) -> Result<()> {
88 let subscription = self.get_subscription(subscription_id).await?;
89
90 self.update_subscription_calls
91 .lock()
92 .push((subscription.id, params));
93
94 Ok(())
95 }
96
97 async fn list_prices(&self) -> Result<Vec<StripePrice>> {
98 let prices = self.prices.lock().values().cloned().collect();
99
100 Ok(prices)
101 }
102
103 async fn list_meters(&self) -> Result<Vec<StripeMeter>> {
104 let meters = self.meters.lock().values().cloned().collect();
105
106 Ok(meters)
107 }
108
109 async fn create_meter_event(&self, params: StripeCreateMeterEventParams<'_>) -> Result<()> {
110 self.create_meter_event_calls
111 .lock()
112 .push(StripeCreateMeterEventCall {
113 identifier: params.identifier.into(),
114 event_name: params.event_name.into(),
115 value: params.payload.value,
116 stripe_customer_id: params.payload.stripe_customer_id.clone(),
117 timestamp: params.timestamp,
118 });
119
120 Ok(())
121 }
122}