#[cfg(test)] mod tests { use std::str::FromStr; use chrono::{DateTime, Utc}; use currency_prices::{ models::{self, ApiResponse, CoinMarketCapConfig, Currency, CurrencyPricesError}, CurrencyPrices, }; use reqwest::StatusCode; use rust_decimal::{prelude::Zero, Decimal}; #[test] fn json_deserialize() { let json_data = r#" { "status": { "timestamp": "2024-01-18T03:22:30.818Z", "error_code": 0, "error_message": null, "elapsed": 0, "credit_count": 1, "notice": null }, "data": { "USD": { "symbol": "arxyw206up9", "id": "2633", "name": "eny6os7xl0j", "amount": 1, "last_updated": "2024-01-18T03:22:30.818Z", "quote": { "BTC": { "price": 8901.07, "last_updated": "2024-01-18T03:22:30.818Z" } } } } } "#; let from_currency = Currency { name: String::from("BTC"), }; let to_currency = Currency { name: String::from("USD"), }; let result: Result = serde_json::from_str(json_data); assert!(result.is_ok()); let usd_price: Decimal = result .as_ref() .unwrap() .data .get(&to_currency.name) .and_then(|data_item| { data_item .quote .get(&from_currency.name) .map(|quote| quote.price) }) .unwrap_or(Decimal::zero()); let last_updated: DateTime = result .unwrap() .data .get(&to_currency.name) .map(|data_item| data_item.last_updated) .unwrap(); let expected_price: Decimal = Decimal::from_str("8901.07").unwrap(); assert_eq!(usd_price, expected_price); let expected_date: DateTime = DateTime::from_str("2024-01-18T03:22:30.818Z").unwrap(); assert_eq!(last_updated, expected_date); assert_eq!(DateTime::::timestamp(&last_updated), 1705548150); } #[tokio::test] async fn get_bitcoin_price_for_dev() { let from_currency = Currency { name: String::from("BTC"), }; let to_currency = Currency { name: String::from("USD"), }; let config = models::CoinMarketCapConfig::get_sandbox_config(); let currency_prices = CurrencyPrices::new(config); let price_response = currency_prices.get_price(from_currency, to_currency).await; assert!(price_response.is_ok()); let currency_price = price_response.unwrap(); assert!(currency_price.price > Decimal::zero()); assert_eq!(currency_price.from_currency.name, String::from("BTC")); assert_eq!(currency_price.to_currency.name, String::from("USD")); } #[tokio::test] async fn get_hydranet_price_for_dev() { let from_currency = Currency { name: String::from("HDN"), }; let to_currency = Currency { name: String::from("USD"), }; let config = models::CoinMarketCapConfig::get_sandbox_config(); let currency_prices = CurrencyPrices::new(config); let price_response = currency_prices.get_price(from_currency, to_currency).await; assert!(price_response.is_ok()); let currency_price = price_response.unwrap(); assert!(currency_price.price > Decimal::zero()); assert_eq!(currency_price.from_currency.name, String::from("HDN")); assert_eq!(currency_price.to_currency.name, String::from("USD")); } #[tokio::test] async fn get_error_for_invalid_api_key() { let from_currency = Currency { name: String::from("HDN"), }; let to_currency = Currency { name: String::from("USD"), }; let config = CoinMarketCapConfig::get_production_config(String::from("invalid_key")); let currency_prices = CurrencyPrices::new(config); let price_response = currency_prices.get_price(from_currency, to_currency).await; assert!(price_response.is_err()); let error = price_response.unwrap_err(); match error { CurrencyPricesError::Custom(_) => panic!("A reqwest error should be received"), CurrencyPricesError::Request(reqwest_error) => { assert!(reqwest_error.is_status()); assert_eq!(reqwest_error.status().unwrap(), StatusCode::UNAUTHORIZED); } }; } }