use wave_claw::error::{GraphqlError, InputError};
use wave_claw::models::*;
use wave_claw::pagination::Connection;
fn load_fixture(name: &str) -> serde_json::Value {
let path = format!("tests/fixtures/{}.json", name);
let content = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("fixture {}: {}", path, e));
serde_json::from_str(&content).unwrap()
}
#[test]
fn deserialize_user() {
let data = load_fixture("get_user");
let user: User = serde_json::from_value(data["data"]["user"].clone()).unwrap();
assert_eq!(user.id, "VXNlcjoxMjM0NTY3ODk=");
assert_eq!(user.default_email.as_deref(), Some("user@example.com"));
assert_eq!(user.first_name.as_deref(), Some("Jane"));
assert_eq!(user.last_name.as_deref(), Some("Doe"));
}
#[test]
fn deserialize_businesses_connection() {
let data = load_fixture("list_businesses");
let conn: Connection<Business> =
serde_json::from_value(data["data"]["businesses"].clone()).unwrap();
let page = conn.into_page();
assert_eq!(page.current_page, 1);
assert_eq!(page.total_pages, Some(1));
assert_eq!(page.total_count, Some(2));
assert_eq!(page.items.len(), 2);
assert!(!page.has_next_page());
let personal = &page.items[0];
assert_eq!(personal.name, "Personal");
assert!(personal.is_personal);
assert!(personal.address.is_none());
let consulting = &page.items[1];
assert_eq!(consulting.name, "Smith Consulting");
assert!(!consulting.is_personal);
assert_eq!(consulting.phone.as_deref(), Some("416-555-1234"));
let addr = consulting.address.as_ref().unwrap();
assert_eq!(addr.city.as_deref(), Some("Toronto"));
assert_eq!(addr.postal_code.as_deref(), Some("M5V 1A1"));
}
#[test]
fn deserialize_customer_create_success() {
let data = load_fixture("customer_create");
let result = &data["data"]["customerCreate"];
assert_eq!(result["didSucceed"].as_bool(), Some(true));
let customer: Customer = serde_json::from_value(result["customer"].clone()).unwrap();
assert_eq!(customer.name, "Acme Corp");
assert_eq!(customer.email.as_deref(), Some("billing@acme.com"));
assert_eq!(customer.first_name.as_deref(), Some("John"));
let addr = customer.address.as_ref().unwrap();
assert_eq!(addr.city.as_deref(), Some("San Francisco"));
}
#[test]
fn deserialize_mutation_failed() {
let data = load_fixture("mutation_failed");
let result = &data["data"]["customerCreate"];
assert_eq!(result["didSucceed"].as_bool(), Some(false));
let errors: Vec<InputError> =
serde_json::from_value(result["inputErrors"].clone()).unwrap();
assert_eq!(errors.len(), 1);
assert_eq!(errors[0].code.as_deref(), Some("REQUIRED"));
assert_eq!(errors[0].message.as_deref(), Some("This field is required."));
assert_eq!(
errors[0].path.as_ref().unwrap(),
&["input".to_string(), "name".to_string()]
);
}
#[test]
fn deserialize_graphql_error() {
let json = r#"{
"message": "Unknown argument \"name\" on field \"business\" of type \"Query\".",
"path": [],
"extensions": {
"id": "e486c5f4-49b0-456f-897c-6d21bdabcde7",
"code": "GRAPHQL_VALIDATION_FAILED"
}
}"#;
let error: GraphqlError = serde_json::from_str(json).unwrap();
assert_eq!(
error.extensions.as_ref().unwrap().code.as_deref(),
Some("GRAPHQL_VALIDATION_FAILED")
);
}
#[test]
fn serialize_customer_create_input() {
use wave_claw::inputs::{AddressInput, CustomerCreateInput};
use wave_claw::enums::{CountryCode, CurrencyCode};
let input = CustomerCreateInput::new("biz-123", "Acme Corp")
.first_name("John")
.email("john@acme.com")
.address(
AddressInput::new()
.city("Toronto")
.country_code(CountryCode::CA)
.postal_code("M5V 1A1"),
)
.currency(CurrencyCode::CAD);
let json = serde_json::to_value(&input).unwrap();
assert_eq!(json["businessId"], "biz-123");
assert_eq!(json["name"], "Acme Corp");
assert_eq!(json["firstName"], "John");
assert_eq!(json["email"], "john@acme.com");
assert_eq!(json["address"]["city"], "Toronto");
assert_eq!(json["address"]["countryCode"], "CA");
assert_eq!(json["currency"], "CAD");
assert!(json.get("phone").is_none());
assert!(json.get("mobile").is_none());
}
#[test]
fn serialize_invoice_create_input() {
use rust_decimal_macros::dec;
use wave_claw::inputs::{InvoiceCreateInput, InvoiceCreateItemInput};
let input = InvoiceCreateInput::new("biz-123", "cust-456")
.items(vec![
InvoiceCreateItemInput::new("prod-789")
.quantity(dec!(2))
.unit_price(dec!(49.99)),
])
.memo("Thanks!");
let json = serde_json::to_value(&input).unwrap();
assert_eq!(json["businessId"], "biz-123");
assert_eq!(json["customerId"], "cust-456");
assert_eq!(json["memo"], "Thanks!");
let items = json["items"].as_array().unwrap();
assert_eq!(items.len(), 1);
assert_eq!(items[0]["productId"], "prod-789");
assert_eq!(items[0]["quantity"], "2");
assert_eq!(items[0]["unitPrice"], "49.99");
}
#[test]
fn serialize_money_transaction_input() {
use chrono::NaiveDate;
use rust_decimal_macros::dec;
use wave_claw::enums::{BalanceType, TransactionDirection};
use wave_claw::inputs::{
MoneyTransactionAnchorInput, MoneyTransactionCreateInput,
MoneyTransactionLineItemInput,
};
let input = MoneyTransactionCreateInput::new(
"biz-123",
"ext-001",
NaiveDate::from_ymd_opt(2025, 3, 1).unwrap(),
"Test transaction",
MoneyTransactionAnchorInput {
account_id: "acct-bank".into(),
amount: dec!(100),
direction: TransactionDirection::Deposit,
},
vec![MoneyTransactionLineItemInput::new(
"acct-income",
dec!(100),
BalanceType::Increase,
)],
);
let json = serde_json::to_value(&input).unwrap();
assert_eq!(json["businessId"], "biz-123");
assert_eq!(json["externalId"], "ext-001");
assert_eq!(json["date"], "2025-03-01");
assert_eq!(json["anchor"]["direction"], "DEPOSIT");
assert_eq!(json["lineItems"][0]["balance"], "INCREASE");
}