road-runner-common 0.9.0

Shared Rust utilities for exchange ecosystem backend services.
Documentation
use road_runner_common::response::{ApiErrorDetail, ApiMeta, ApiResponse};

#[test]
fn api_meta_preserves_request_id_and_formats_timestamp() {
    // Arrange / Act
    let meta = ApiMeta::new("rid-1");

    // Assert
    assert_eq!(meta.request_id, "rid-1");
    assert!(meta.timestamp.contains('T'));
    assert!(meta.timestamp.ends_with('Z'));
}

#[test]
fn error_detail_builder_sets_optional_field() {
    // Arrange / Act
    let detail = ApiErrorDetail::new("VALIDATION_ERROR", "bad").with_field("email");

    // Assert
    assert_eq!(detail.code, "VALIDATION_ERROR");
    assert_eq!(detail.message, "bad");
    assert_eq!(detail.field.as_deref(), Some("email"));
}

#[test]
fn ok_response_contains_data_and_empty_errors() {
    // Arrange / Act
    let response = ApiResponse::ok(42, "rid-ok");

    // Assert
    assert!(response.success);
    assert_eq!(response.data, Some(42));
    assert!(response.errors.is_empty());
    assert_eq!(response.meta.request_id, "rid-ok");
}

#[test]
fn empty_ok_response_has_no_data() {
    // Arrange / Act
    let response = ApiResponse::<()>::empty_ok("rid-empty");

    // Assert
    assert!(response.success);
    assert!(response.data.is_none());
    assert!(response.errors.is_empty());
}

#[test]
fn err_response_contains_errors_and_no_data() {
    // Arrange
    let errors = vec![ApiErrorDetail::new("FORBIDDEN", "no")];

    // Act
    let response = ApiResponse::<()>::err(errors, "rid-err");

    // Assert
    assert!(!response.success);
    assert!(response.data.is_none());
    assert_eq!(response.errors[0].code, "FORBIDDEN");
    assert_eq!(response.meta.request_id, "rid-err");
}