use super::*;
#[test]
fn parse_slash_format() {
let sym: Symbol = "BTC/USDT"
.parse()
.expect("'BTC/USDT' is a valid Symbol literal");
assert_eq!(sym.base(), "BTC");
assert_eq!(sym.quote(), "USDT");
}
#[test]
fn parse_dash_format() {
let sym: Symbol = "ETH-USD"
.parse()
.expect("'ETH-USD' is a valid Symbol literal");
assert_eq!(sym.base(), "ETH");
assert_eq!(sym.quote(), "USD");
}
#[test]
fn canonical_format() {
let sym: Symbol = "eth-btc"
.parse()
.expect("'eth-btc' is a valid Symbol literal");
assert_eq!(sym.canonical(), "ETH/BTC");
}
#[test]
fn parse_invalid_format_returns_error() {
let result: Result<Symbol, _> = "BTCUSDT".parse();
assert!(matches!(result, Err(SymbolError::InvalidFormat(s)) if s == "BTCUSDT"));
}
#[test]
fn parse_empty_returns_error() {
let result: Result<Symbol, _> = "".parse();
assert!(matches!(result, Err(SymbolError::InvalidFormat(_))));
}
#[test]
fn is_crypto_true_for_stablecoins() {
assert!("BTC/USDT"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
assert!("ETH/USDC"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
assert!("SOL/BUSD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
assert!("DOGE/DAI"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
}
#[test]
fn is_crypto_true_for_btc_eth_pairs() {
assert!("ETH/BTC"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
assert!("SOL/ETH"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
}
#[test]
fn is_crypto_false_for_fiat() {
assert!(!"AAPL/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
assert!(!"EUR/GBP"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto());
}
#[test]
fn is_crypto_true_for_crypto_base_with_fiat_quote() {
assert!(
"BTC/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"BTC/USD should be crypto (BTC is a cryptocurrency)"
);
assert!(
"ETH/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"ETH/USD should be crypto (ETH is a cryptocurrency)"
);
assert!(
"SOL/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"SOL/USD should be crypto (SOL is a cryptocurrency)"
);
}
#[test]
fn is_crypto_false_for_equities_with_fiat_quote() {
assert!(
!"TSLA/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"TSLA/USD should NOT be crypto (TSLA is an equity)"
);
assert!(
!"AAPL/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"AAPL/USD should NOT be crypto (AAPL is an equity)"
);
assert!(
!"MSFT/USD"
.parse::<Symbol>()
.expect("valid Symbol")
.is_crypto(),
"MSFT/USD should NOT be crypto (MSFT is an equity)"
);
}
#[test]
fn serde_roundtrip() {
let original: Symbol = "SOL/USDC".parse().expect("valid symbol");
let json = serde_json::to_string(&original).expect("valid json");
let parsed: Symbol = serde_json::from_str(&json).expect("valid json");
assert_eq!(parsed, original);
assert_eq!(parsed.base(), "SOL");
assert_eq!(parsed.quote(), "USDC");
}
#[test]
fn symbol_error_display_contains_input() {
let err = SymbolError::InvalidFormat("BTCUSDT".to_string());
assert!(err.to_string().contains("BTCUSDT"));
}
#[test]
fn parse_normalizes_to_uppercase() {
let sym: Symbol = "btc/usdt".parse().expect("valid symbol");
assert_eq!(sym.base(), "BTC");
assert_eq!(sym.quote(), "USDT");
}