fake_stripe_client.rs

 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, StripeCustomer, StripeCustomerId, StripeMeter,
11    StripeMeterId, StripePrice, StripePriceId, StripeSubscription, StripeSubscriptionId,
12    UpdateSubscriptionParams,
13};
14
15pub struct FakeStripeClient {
16    pub customers: Arc<Mutex<HashMap<StripeCustomerId, StripeCustomer>>>,
17    pub subscriptions: Arc<Mutex<HashMap<StripeSubscriptionId, StripeSubscription>>>,
18    pub update_subscription_calls:
19        Arc<Mutex<Vec<(StripeSubscriptionId, UpdateSubscriptionParams)>>>,
20    pub prices: Arc<Mutex<HashMap<StripePriceId, StripePrice>>>,
21    pub meters: Arc<Mutex<HashMap<StripeMeterId, StripeMeter>>>,
22}
23
24impl FakeStripeClient {
25    pub fn new() -> Self {
26        Self {
27            customers: Arc::new(Mutex::new(HashMap::default())),
28            subscriptions: Arc::new(Mutex::new(HashMap::default())),
29            update_subscription_calls: Arc::new(Mutex::new(Vec::new())),
30            prices: Arc::new(Mutex::new(HashMap::default())),
31            meters: Arc::new(Mutex::new(HashMap::default())),
32        }
33    }
34}
35
36#[async_trait]
37impl StripeClient for FakeStripeClient {
38    async fn list_customers_by_email(&self, email: &str) -> Result<Vec<StripeCustomer>> {
39        Ok(self
40            .customers
41            .lock()
42            .values()
43            .filter(|customer| customer.email.as_deref() == Some(email))
44            .cloned()
45            .collect())
46    }
47
48    async fn create_customer(&self, params: CreateCustomerParams<'_>) -> Result<StripeCustomer> {
49        let customer = StripeCustomer {
50            id: StripeCustomerId(format!("cus_{}", Uuid::new_v4()).into()),
51            email: params.email.map(|email| email.to_string()),
52        };
53
54        self.customers
55            .lock()
56            .insert(customer.id.clone(), customer.clone());
57
58        Ok(customer)
59    }
60
61    async fn get_subscription(
62        &self,
63        subscription_id: &StripeSubscriptionId,
64    ) -> Result<StripeSubscription> {
65        self.subscriptions
66            .lock()
67            .get(subscription_id)
68            .cloned()
69            .ok_or_else(|| anyhow!("no subscription found for {subscription_id:?}"))
70    }
71
72    async fn update_subscription(
73        &self,
74        subscription_id: &StripeSubscriptionId,
75        params: UpdateSubscriptionParams,
76    ) -> Result<()> {
77        let subscription = self.get_subscription(subscription_id).await?;
78
79        self.update_subscription_calls
80            .lock()
81            .push((subscription.id, params));
82
83        Ok(())
84    }
85
86    async fn list_prices(&self) -> Result<Vec<StripePrice>> {
87        let prices = self.prices.lock().values().cloned().collect();
88
89        Ok(prices)
90    }
91
92    async fn list_meters(&self) -> Result<Vec<StripeMeter>> {
93        let meters = self.meters.lock().values().cloned().collect();
94
95        Ok(meters)
96    }
97}