sumup 0.5.14

Rust SDK for the SumUp API.
Documentation
use std::process::Command;
use std::time::Duration;

use serde_json::json;
use sumup::{Authorization, Client, version};
use wiremock::matchers::{header, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};

const ENV_TEST_CASE: &str = "SUMUP_RS_ENV_TEST_CASE";

fn run_environment_test(case: &str, api_key: Option<&str>) {
    let mut command = Command::new(std::env::current_exe().expect("resolve current test binary"));
    command
        .args(["--exact", "client_environment_case"])
        .env(ENV_TEST_CASE, case);

    if let Some(api_key) = api_key {
        command.env("SUMUP_API_KEY", api_key);
    } else {
        command.env_remove("SUMUP_API_KEY");
    }

    let output = command.output().expect("run environment test subprocess");
    assert!(
        output.status.success(),
        "environment test subprocess failed:\n{}",
        String::from_utf8_lossy(&output.stderr)
    );
}

#[test]
fn client_environment_case() {
    let Ok(case) = std::env::var(ENV_TEST_CASE) else {
        return;
    };

    let client = Client::new();
    match case.as_str() {
        "reads_authorization" => assert_eq!(client.authorization(), Some("env-token")),
        "overrides_authorization" => assert_eq!(
            client
                .with_authorization(Authorization::api_key("override-token"))
                .authorization(),
            Some("override-token")
        ),
        "missing_authorization" => assert!(client.authorization().is_none()),
        _ => panic!("unknown environment test case: {case}"),
    }
}

#[test]
fn client_uses_default_base_url() {
    let client = Client::default();
    assert_eq!(client.base_url(), "https://api.sumup.com");
}

#[test]
fn client_with_base_url_overrides_default() {
    let client = Client::new().with_base_url("https://mock.sumup.internal.test");
    assert_eq!(client.base_url(), "https://mock.sumup.internal.test");
}

#[test]
fn client_with_timeout_updates_timeout() {
    let timeout = Duration::from_secs(42);
    let client = Client::new().with_timeout(timeout);
    assert_eq!(client.timeout(), timeout);
}

#[test]
fn client_reads_authorization_from_env() {
    run_environment_test("reads_authorization", Some("env-token"));
}

#[test]
fn client_with_authorization_overrides_env_value() {
    run_environment_test("overrides_authorization", Some("env-token"));
}

#[tokio::test]
async fn client_requests_include_user_agent_and_custom_authorization() {
    let server = MockServer::start().await;
    let override_token = "override-token";
    let expected_auth = format!("Bearer {}", override_token);
    let expected_user_agent = version::user_agent();

    let _mock = Mock::given(method("GET"))
        .and(path("/v0.1/checkouts"))
        .and(header("User-Agent", expected_user_agent.as_str()))
        .and(header("Authorization", expected_auth.as_str()))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!([])))
        .expect(1)
        .mount_as_scoped(&server)
        .await;

    let client = Client::new()
        .with_base_url(server.uri())
        .with_authorization(Authorization::api_key(override_token));

    client
        .checkouts()
        .list(sumup::resources::checkouts::ListParams::default())
        .await
        .expect("request should succeed");
}

#[tokio::test]
async fn client_requests_include_runtime_headers() {
    let server = MockServer::start().await;
    let expected_user_agent = version::user_agent();

    let mut mock = Mock::given(method("GET"))
        .and(path("/v0.1/checkouts"))
        .and(header("User-Agent", expected_user_agent.as_str()));

    for (header_name, header_value) in version::runtime_info() {
        mock = mock.and(header(header_name, header_value.as_str()));
    }

    let _mock = mock
        .respond_with(ResponseTemplate::new(200).set_body_json(json!([])))
        .expect(1)
        .mount_as_scoped(&server)
        .await;

    let client = Client::new().with_base_url(server.uri());

    client
        .checkouts()
        .list(sumup::resources::checkouts::ListParams::default())
        .await
        .expect("request should succeed");
}

#[test]
fn client_returns_none_when_authorization_missing() {
    run_environment_test("missing_authorization", None);
}