rust-genai 0.3.1

Rust SDK for the Google Gemini API and Vertex AI
Documentation
use serde_json::json;
use wiremock::matchers::{method, path, query_param, query_param_is_missing};
use wiremock::{Mock, MockServer, ResponseTemplate};

use rust_genai::types::operations::ListOperationsConfig;

mod support;
use support::build_gemini_client_with_version;

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

    Mock::given(method("GET"))
        .and(path("/v1beta/operations/op1"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "name": "operations/op1",
            "done": true
        })))
        .mount(&server)
        .await;

    Mock::given(method("GET"))
        .and(path("/v1beta/operations/bad"))
        .respond_with(ResponseTemplate::new(500).set_body_string("boom"))
        .mount(&server)
        .await;

    Mock::given(method("GET"))
        .and(path("/v1beta/operations"))
        .and(query_param("pageSize", "2"))
        .and(query_param_is_missing("pageToken"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "operations": [{"name": "operations/op1"}],
            "nextPageToken": "next"
        })))
        .mount(&server)
        .await;

    Mock::given(method("GET"))
        .and(path("/v1beta/operations"))
        .and(query_param("pageSize", "2"))
        .and(query_param("pageToken", "next"))
        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
            "operations": [{"name": "operations/op2"}]
        })))
        .mount(&server)
        .await;

    let client = build_gemini_client_with_version(&server.uri(), "v1beta");
    let ops = client.operations();

    let op = ops.get("op1").await.unwrap();
    assert_eq!(op.name.as_deref(), Some("operations/op1"));

    let err = ops.get("bad").await.unwrap_err();
    assert!(matches!(err, rust_genai::Error::ApiError { .. }));

    let list = ops
        .list_with_config(ListOperationsConfig {
            page_size: Some(2),
            ..Default::default()
        })
        .await
        .unwrap();
    assert_eq!(list.operations.unwrap().len(), 1);

    let all = ops
        .all_with_config(ListOperationsConfig {
            page_size: Some(2),
            ..Default::default()
        })
        .await
        .unwrap();
    assert_eq!(all.len(), 2);
}

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

    Mock::given(method("GET"))
        .and(path("/v1beta/operations"))
        .respond_with(ResponseTemplate::new(503).set_body_json(json!({
            "error": {
                "message": "operations unavailable",
                "status": "UNAVAILABLE"
            }
        })))
        .mount(&server)
        .await;

    let client = build_gemini_client_with_version(&server.uri(), "v1beta");
    let err = client.operations().list().await.unwrap_err();
    assert_eq!(err.status().unwrap().as_u16(), 503);
    assert!(err.is_retryable());
}