reevit 0.1.0

Official Rust SDK for the Reevit payments API
Documentation
use reevit::{
    Client, ConnectionRequest, CustomerListOptions, InvoiceListOptions, PaginationOptions,
    SubscriptionListOptions, WebhookEventListOptions,
};
use serde_json::json;
use wiremock::matchers::{method, path, query_param};
use wiremock::{Mock, MockServer, ResponseTemplate};

#[tokio::test]
async fn customer_lists_accept_wrapped_collection_responses() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/customers"))
        .and(query_param("limit", "25"))
        .and(query_param("search", "ama"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "customers": [{
                "id": "cus_123",
                "email": "ama@example.com",
                "name": "Ama"
            }]
        })))
        .mount(&server)
        .await;

    let client = Client::builder("pfk_test_example.secret", "org_123")
        .base_url(server.uri())
        .build()
        .unwrap();
    let customers = client
        .customers()
        .list(&CustomerListOptions {
            limit: Some(25),
            search: Some("ama".into()),
            ..CustomerListOptions::default()
        })
        .await
        .unwrap();

    assert_eq!(customers.len(), 1);
    assert_eq!(customers[0].id, "cus_123");
}

fn client(server: &MockServer) -> Client {
    Client::builder("pfk_test_example.secret", "org_123")
        .base_url(server.uri())
        .build()
        .unwrap()
}

#[tokio::test]
async fn connections_test_accepts_the_api_ok_response_shape() {
    let server = MockServer::start().await;
    Mock::given(method("POST"))
        .and(path("/v1/connections/test"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({"ok": true})))
        .mount(&server)
        .await;

    let valid = client(&server)
        .connections()
        .test(
            &ConnectionRequest {
                provider: "paystack".into(),
                mode: "test".into(),
                credentials: Default::default(),
                ..ConnectionRequest::default()
            },
            Default::default(),
        )
        .await
        .unwrap();

    assert!(valid);
}

#[tokio::test]
async fn subscriptions_list_uses_the_subscriptions_collection() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/subscriptions"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({"subscriptions": []})))
        .mount(&server)
        .await;

    let subscriptions = client(&server)
        .subscriptions()
        .list(&SubscriptionListOptions::default())
        .await
        .unwrap();
    assert!(subscriptions.is_empty());
}

#[tokio::test]
async fn fraud_get_decodes_the_policy() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/policies/fraud"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "prefer": ["paystack"],
            "max_amount": 100000,
            "blocked_bins": [],
            "allowed_bins": [],
            "velocity_max_per_minute": 10
        })))
        .mount(&server)
        .await;

    let policy = client(&server).fraud().get().await.unwrap();
    assert_eq!(policy.prefer, ["paystack"]);
}

#[tokio::test]
async fn payment_links_resolve_public_codes() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/pay/summer-sale"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "id": "plink_123",
            "code": "summer-sale"
        })))
        .mount(&server)
        .await;

    let link = client(&server)
        .payment_links()
        .get_by_code("summer-sale")
        .await
        .unwrap();
    assert_eq!(link.id, "plink_123");
}

#[tokio::test]
async fn webhooks_list_uses_the_events_collection() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/webhooks/events"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({"events": []})))
        .mount(&server)
        .await;

    let events = client(&server)
        .webhooks()
        .list_events(&WebhookEventListOptions::default())
        .await
        .unwrap();
    assert!(events.is_empty());
}

#[tokio::test]
async fn routing_rules_list_uses_the_rules_collection() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/routing-rules"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({"rules": []})))
        .mount(&server)
        .await;

    let rules = client(&server)
        .routing_rules()
        .list(&PaginationOptions::default())
        .await
        .unwrap();
    assert!(rules.is_empty());
}

#[tokio::test]
async fn invoices_list_uses_the_invoices_collection() {
    let server = MockServer::start().await;
    Mock::given(method("GET"))
        .and(path("/v1/invoices"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({"invoices": []})))
        .mount(&server)
        .await;

    let invoices = client(&server)
        .invoices()
        .list(&InvoiceListOptions::default())
        .await
        .unwrap();
    assert!(invoices.is_empty());
}