Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions jive-api/tests/contract_decimal_serialization.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use chrono::{TimeZone, Utc};
use rust_decimal::Decimal;
use serde_json::Value;

#[test]
fn global_market_stats_decimal_serializes_as_string() {
use jive_money_api::models::global_market::GlobalMarketStats;

let stats = GlobalMarketStats {
total_market_cap_usd: Decimal::new(12_345_000_000, 0),
total_volume_24h_usd: Decimal::new(987_654_321, 0),
btc_dominance_percentage: Decimal::new(485, 1), // 48.5
eth_dominance_percentage: Some(Decimal::new(180, 1)), // 18.0
active_cryptocurrencies: 1000,
markets: Some(500),
updated_at: 1_700_000_000,
};

let val: Value = serde_json::to_value(&stats).expect("serialize market stats");
for key in [
"total_market_cap_usd",
"total_volume_24h_usd",
"btc_dominance_percentage",
] {
assert!(val.get(key).and_then(|v| v.as_str()).is_some(), "{} should be string", key);
}
// updated_at is numeric unix timestamp
assert!(val.get("updated_at").and_then(|v| v.as_i64()).is_some());
Comment on lines +27 to +28

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test function is named global_market_stats_decimal_serializes_as_string, which implies its scope is limited to testing Decimal fields. The added assertion for updated_at (an i64) is outside this scope. While testing the entire contract is important, mixing concerns within a single test can make the test suite harder to understand and maintain. It's best practice for a test to have a single, clear purpose reflected in its name.

To improve clarity, I recommend moving this check to a separate test function, for example global_market_stats_numeric_fields_are_serialized_correctly. This would keep your tests focused and self-documenting.

assert!(val
.get("eth_dominance_percentage")
.and_then(|v| v.as_str())
.is_some());
}

#[test]
fn account_response_decimal_serializes_as_string() {
use jive_money_api::handlers::accounts::AccountResponse;
use uuid::Uuid;

let resp = AccountResponse {
id: Uuid::nil(),
ledger_id: Uuid::nil(),
bank_id: None,
name: "Checking".to_string(),
account_type: "asset".to_string(),
account_number: None,
institution_name: None,
currency: "USD".to_string(),
current_balance: Decimal::new(12345, 2),
available_balance: Some(Decimal::new(12000, 2)),
credit_limit: None,
status: "active".to_string(),
is_manual: true,
color: None,
icon: None,
notes: None,
created_at: Utc.timestamp_opt(1_700_000_000, 0).unwrap(),
updated_at: Utc.timestamp_opt(1_700_000_000, 0).unwrap(),
};

let val: Value = serde_json::to_value(&resp).expect("serialize account response");
for key in ["current_balance"] {
assert!(val.get(key).and_then(|v| v.as_str()).is_some(), "{} should be string", key);
}
// Optional Decimal fields should also be strings when present
assert!(val
.get("available_balance")
.and_then(|v| v.as_str())
.is_some());
}