use std::{fs::File, path::Path}; use rust_decimal::Decimal; use fugle::{ errors::{ErrorResponse, FugleError}, schema::{ CandlesResponse, ChartResponse, DealtsResponse, MetaResponse, QuoteResponse, VolumesResponse, }, }; #[test] fn test_volumes_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/volumes_response.json")).unwrap(); let res: VolumesResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("EQUITY", res.data.info.typ); assert_eq!(3, res.data.volumes.len()); } #[test] fn test_chart_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/chart_response.json")).unwrap(); let res: ChartResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("EQUITY", res.data.info.typ); assert_eq!(263, res.data.chart.open.len()); assert_eq!(263, res.data.chart.high.len()); assert_eq!(263, res.data.chart.low.len()); assert_eq!(263, res.data.chart.close.len()); assert_eq!(263, res.data.chart.unix_timestamp.len()); } #[test] fn test_quote_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/quote_response.json")).unwrap(); let res: QuoteResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("EQUITY", res.data.info.typ); assert_eq!( (-0.19f64).to_string(), res.data.quote.change_percent.to_string() ); assert_eq!(0.38f64.to_string(), res.data.quote.amplitude.to_string()); assert_eq!(5, res.data.quote.order.bids.len()); assert_eq!(5, res.data.quote.order.asks.len()); assert_eq!( 26.5f64.to_string(), res.data.quote.price_high.price.to_string() ); assert_eq!( 26.4f64.to_string(), res.data.quote.price_low.price.to_string() ); assert_eq!( 26.5f64.to_string(), res.data.quote.price_open.price.to_string() ); assert_eq!( 26.46f64.to_string(), res.data.quote.price_avg.price.to_string() ); } #[test] fn test_meta_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/meta_response.json")).unwrap(); let res: MetaResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("EQUITY", res.data.info.typ); assert_eq!( 26.5f64.to_string(), res.data.meta.price_reference.to_string() ); assert_eq!( 29.15f64.to_string(), res.data.meta.price_high_limit.to_string() ); assert_eq!( 23.85f64.to_string(), res.data.meta.price_low_limit.to_string() ); assert!(res.data.meta.can_day_buy_sell); assert_eq!("玉山金", res.data.meta.name_zh_tw); assert_eq!("金融保險", res.data.meta.industry_zh_tw); } #[test] fn test_dealts_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/dealts_response.json")).unwrap(); let res: DealtsResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("EQUITY", res.data.info.typ); assert_eq!(5, res.data.dealts.len()); } #[test] fn test_volumes_response_with_oddlot_deserialize() { let json_file = File::open(Path::new( "tests/testdata/volumes_response_with_oddlot.json", )) .unwrap(); let res: VolumesResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("ODDLOT", res.data.info.typ); assert_eq!(3, res.data.volumes.len()); } #[test] fn test_chart_response_with_oddlot_deserialize() { let json_file = File::open(Path::new("tests/testdata/chart_response_with_oddlot.json")).unwrap(); let res: ChartResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("TSE", res.data.info.market); assert_eq!("ODDLOT", res.data.info.typ); assert_eq!("2884", res.data.info.symbol_id); assert_eq!(87, res.data.chart.open.len()); assert_eq!(87, res.data.chart.high.len()); assert_eq!(87, res.data.chart.low.len()); assert_eq!(87, res.data.chart.close.len()); assert_eq!(87, res.data.chart.unix_timestamp.len()); } #[test] fn test_quote_response_with_oddlot_deserialize() { let json_file = File::open(Path::new("tests/testdata/quote_response_with_oddlot.json")).unwrap(); let res: QuoteResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("ODDLOT", res.data.info.typ); assert_eq!( (-0.19f64).to_string(), res.data.quote.change_percent.to_string() ); assert_eq!(0.19f64.to_string(), res.data.quote.amplitude.to_string()); assert_eq!(5, res.data.quote.order.bids.len()); assert_eq!(5, res.data.quote.order.asks.len()); assert_eq!( 26.45f64.to_string(), res.data.quote.price_high.price.to_string() ); assert_eq!( 26.4f64.to_string(), res.data.quote.price_low.price.to_string() ); assert_eq!( 26.45f64.to_string(), res.data.quote.price_open.price.to_string() ); assert_eq!( 26.43f64.to_string(), res.data.quote.price_avg.price.to_string() ); } #[test] fn test_meta_response_with_oddlot_deserialize() { let json_file = File::open(Path::new("tests/testdata/meta_response_with_oddlot.json")).unwrap(); let res: MetaResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("ODDLOT", res.data.info.typ); assert_eq!( 26.5f64.to_string(), res.data.meta.price_reference.to_string() ); assert_eq!( 29.15f64.to_string(), res.data.meta.price_high_limit.to_string() ); assert_eq!( 23.85f64.to_string(), res.data.meta.price_low_limit.to_string() ); assert!(!res.data.meta.can_day_buy_sell); assert_eq!("玉山金", res.data.meta.name_zh_tw); } #[test] fn test_dealts_response_with_oddlot_deserialize() { let json_file = File::open(Path::new("tests/testdata/dealts_response_with_oddlot.json")).unwrap(); let res: DealtsResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("0.3.0", res.api_version); assert_eq!("2884", res.data.info.symbol_id); assert_eq!("TSE", res.data.info.market); assert_eq!("ODDLOT", res.data.info.typ); assert_eq!(5, res.data.dealts.len()); } #[test] fn test_candles_response_deserialize() { let json_file = File::open(Path::new("tests/testdata/candles_response.json")).unwrap(); let res: CandlesResponse = serde_json::from_reader(json_file).unwrap(); assert_eq!("2884", res.symbol_id); assert_eq!("TSE", res.market); assert_eq!("EQUITY", res.typ); assert_eq!("TWSE", res.exchange); assert_eq!(6, res.candles.len()); assert_eq!(Decimal::new(3340, 2), res.candles[0].open); assert_eq!(Decimal::new(3325, 2), res.candles[1].high); assert_eq!(Decimal::new(3250, 2), res.candles[2].low); assert_eq!(Decimal::new(3245, 2), res.candles[3].close); assert_eq!(36634330, res.candles[4].volume); assert_eq!(2022, res.candles[5].date.year()); assert_eq!(time::Month::April, res.candles[5].date.month()); assert_eq!(21, res.candles[5].date.day()); } #[test] fn test_error_response_deserialize() { let input_json = r#"{ "apiVersion": "0.3.0", "error": { "code": 401, "message": "Unauthorized" } }"#; let err: ErrorResponse = serde_json::from_str(input_json).unwrap(); let got = FugleError::from(err); match got { FugleError::Unauthorized => {} _ => unreachable!(), } let input_json = r#"{ "apiVersion": "0.3.0", "error": { "code": 403, "message": "RateLimitExceeded" } }"#; let err: ErrorResponse = serde_json::from_str(input_json).unwrap(); let got = FugleError::from(err); match got { FugleError::RateLimitExceeded => {} _ => unreachable!(), } let input_json = r#"{ "apiVersion": "0.3.0", "error": { "code": 404, "message": "ResourceNotFound" } }"#; let err: ErrorResponse = serde_json::from_str(input_json).unwrap(); let got = FugleError::from(err); match got { FugleError::ResourceNotFound => {} _ => unreachable!(), } let input_json = r#"{ "statusCode": 400, "message": [ "from must be a valid ISO 8601 date string", "to must be a valid ISO 8601 date string" ], "error": "Bad Request" }"#; let err: ErrorResponse = serde_json::from_str(input_json).unwrap(); let got = FugleError::from(err); match got { FugleError::General(_) => {} _ => unreachable!(), } let input_json = r#"{ "statusCode": 401, "message": "Unauthorized" }"#; let err: ErrorResponse = serde_json::from_str(input_json).unwrap(); let got = FugleError::from(err); match got { FugleError::Unauthorized => {} _ => unreachable!(), } }