zenwave 0.7.0

Ergonomic HTTP client framework.
Documentation
//! Integration tests for Zenwave using real HTTP requests.

mod common;
use common::httpbin_uri;
use serde_json::Value;
use zenwave::{Client, Method, client, get};

fn endpoint(path: &str) -> String {
    httpbin_uri(path)
}

#[test_executors::async_test]
async fn test_real_world_api_request() {
    // Test with a real JSON API
    let response = get(endpoint("/json")).await.unwrap();
    assert!(response.status().is_success());

    let json: Value = response.into_body().into_json().await.unwrap();
    assert!(json.is_object());
}

#[test_executors::async_test]
async fn test_user_agent_header() {
    let response = get(endpoint("/user-agent")).await.unwrap();
    let text = response.into_body().into_string().await.unwrap();

    // Should contain some user agent info
    assert!(!text.is_empty());
}

#[test_executors::async_test]
async fn test_custom_headers() {
    let mut client = client();
    let response = client.get(endpoint("/headers")).unwrap().await.unwrap();
    let text = response.into_body().into_string().await.unwrap();

    // Should contain header information
    assert!(text.contains("headers"));
}

#[test_executors::async_test]
async fn test_post_with_json_body() {
    let mut client = client();
    let request = client.method(Method::POST, endpoint("/post")).unwrap();
    // Note: In a real implementation, you'd want to add a body() method to RequestBuilder
    let response = request.await;

    assert!(response.is_ok());
    let response = response.unwrap();
    assert!(response.status().is_success());
}

#[test_executors::async_test]
async fn test_response_status_codes() {
    for status_code in [200, 201, 400, 401, 403, 404, 500, 502, 503] {
        let url = endpoint(&format!("/status/{status_code}"));
        let response = get(url).await;
        if status_code < 400 {
            let response = response.unwrap();
            assert_eq!(response.status().as_u16(), status_code);
        } else {
            let error = response.expect_err("expected error status to surface as Err");
            let description = format!("{error}");
            assert!(
                description.contains(&status_code.to_string()),
                "error message should mention status code {status_code}: {description}"
            );
        }
    }
}

#[test_executors::async_test]
async fn test_redirect_chain() {
    let mut client = client();

    // Test a redirect chain
    let response = client.get(endpoint("/redirect/5")).unwrap().await.unwrap();
    assert!(response.status().is_success());
}

#[test_executors::async_test]
async fn test_large_response() {
    // Test handling of larger responses
    let response = get(endpoint("/base64/aGVsbG8gd29ybGQ=")).await;
    assert!(response.is_ok());
    let response = response.unwrap();
    let body = response.into_body().into_bytes().await;
    assert!(body.is_ok());
    let bytes = body.unwrap();
    assert!(!bytes.is_empty());
}

#[test_executors::async_test]
async fn test_gzip_compression() {
    // Local test server advertises gzip support
    let response = get(endpoint("/gzip")).await;
    assert!(response.is_ok());
    let response = response.unwrap();
    let bytes = response.into_body().into_bytes().await.unwrap();
    // Should get some response data (gzipped content is handled by the HTTP client)
    assert!(!bytes.is_empty());
}

#[test_executors::async_test]
async fn test_cookie_persistence() {
    let mut client = client().enable_cookie();

    // Set a cookie
    let _response = client
        .get(endpoint("/cookies/set/test/cookievalue"))
        .unwrap()
        .await
        .unwrap();

    // Verify cookie is sent in subsequent request
    let response = client.get(endpoint("/cookies")).unwrap().await.unwrap();
    let body = response.into_body().into_string().await.unwrap();
    assert!(body.contains("test"));
    assert!(body.contains("cookievalue"));
}

#[test_executors::async_test]
async fn test_method_overrides() {
    let mut client = client();

    // Test different HTTP methods
    let methods = [
        (Method::GET, "/get"),
        (Method::POST, "/post"),
        (Method::PUT, "/put"),
        (Method::DELETE, "/delete"),
        (Method::PATCH, "/patch"),
    ];

    for (method, url) in methods {
        let method_clone = method.clone();
        let response = client.method(method, endpoint(url)).unwrap().await;
        assert!(response.is_ok(), "Failed for method: {method_clone:?}");
        let response = response.unwrap();
        assert!(
            response.status().is_success(),
            "Failed for method: {method_clone:?}"
        );
    }
}