use reevit::{
Client, ConnectionListOptions, 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 connections_list_all_follows_pagination_and_filters() {
let server = MockServer::start().await;
let filters = [
("provider", "paystack"),
("mode", "live"),
("status", "active"),
("label", "primary"),
("limit", "200"),
];
let mut first = Mock::given(method("GET")).and(path("/v1/connections"));
let mut second = Mock::given(method("GET")).and(path("/v1/connections"));
for (key, value) in filters {
first = first.and(query_param(key, value));
second = second.and(query_param(key, value));
}
first
.and(query_param("offset", "0"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"connections": [
{"id": "conn_1", "provider": "paystack", "mode": "live", "status": "active",
"name_match_status": "match"},
{"id": "conn_2", "provider": "paystack", "mode": "live", "status": "active"}
],
"pagination": {"total": 3, "limit": 200, "offset": 0}
})))
.expect(1)
.mount(&server)
.await;
second
.and(query_param("offset", "2"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"connections": [
{"id": "conn_3", "provider": "paystack", "mode": "live", "status": "active"}
],
"pagination": {"total": 3, "limit": 200, "offset": 2}
})))
.expect(1)
.mount(&server)
.await;
let connections = client(&server)
.connections()
.list_all(&ConnectionListOptions {
provider: Some("paystack".into()),
mode: Some("live".into()),
status: Some("active".into()),
label: Some("primary".into()),
..ConnectionListOptions::default()
})
.await
.unwrap();
assert_eq!(
connections
.iter()
.map(|connection| connection.id.as_str())
.collect::<Vec<_>>(),
["conn_1", "conn_2", "conn_3"]
);
assert_eq!(connections[0].name_match_status.as_deref(), Some("match"));
}
#[tokio::test]
async fn connections_list_labels_uses_the_labels_endpoint() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/connections/labels"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!([
{"label": "primary", "total": 2}
])))
.mount(&server)
.await;
let labels = client(&server).connections().list_labels().await.unwrap();
assert_eq!(labels[0].label, "primary");
assert_eq!(labels[0].total, 2);
}
#[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());
}