parcelwing 0.1.0

Official Rust SDK for the Parcel Wing API.
Documentation
use httpmock::prelude::*;
use parcelwing::{Client, EmailSendRequest};

#[tokio::test]
async fn sends_email_request_and_returns_queued_emails() {
    let server = MockServer::start();

    let mock = server.mock(|when, then| {
        when.method(POST)
            .path("/api/emails")
            .header("authorization", "Bearer pw_test_123")
            .json_body_obj(&serde_json::json!({
                "from": "Parcel Wing <hello@example.com>",
                "to": "you@example.com",
                "subject": "Hello",
                "text": "It works!"
            }));

        then.status(202)
            .header("content-type", "application/json")
            .json_body_obj(&serde_json::json!({
                "object": "list",
                "data": [
                    {
                        "object": "email",
                        "id": "msg_123",
                        "to": "you@example.com",
                        "status": "queued"
                    }
                ],
                "pagination": null
            }));
    });

    let client = Client::builder("pw_test_123")
        .base_url(server.base_url())
        .build()
        .unwrap();

    let emails = client
        .emails()
        .send(
            EmailSendRequest::new("Parcel Wing <hello@example.com>", "you@example.com")
                .subject("Hello")
                .text("It works!"),
        )
        .await
        .unwrap();

    mock.assert();
    assert_eq!(emails.len(), 1);
    assert_eq!(emails[0].id, "msg_123");
    assert_eq!(emails[0].status, "queued");
}

#[tokio::test]
async fn maps_api_error_payload() {
    let server = MockServer::start();

    server.mock(|when, then| {
        when.method(POST).path("/api/emails");
        then.status(400)
            .header("content-type", "application/json")
            .json_body_obj(&serde_json::json!({
                "error": {
                    "type": "validation_error",
                    "code": "invalid_request_body",
                    "message": "Invalid request body.",
                    "request_id": "req_123"
                }
            }));
    });

    let client = Client::builder("pw_test_123")
        .base_url(server.base_url())
        .build()
        .unwrap();

    let error = client
        .emails()
        .send(EmailSendRequest::new("bad", "you@example.com"))
        .await
        .unwrap_err();

    match error {
        parcelwing::Error::Api(api_error) => {
            assert_eq!(api_error.status(), 400);
            assert_eq!(api_error.code.as_deref(), Some("invalid_request_body"));
            assert_eq!(api_error.request_id.as_deref(), Some("req_123"));
        }
        other => panic!("expected API error, got {other:?}"),
    }
}