1pub use super::format::{
7 format_discover_fields, format_field_types, format_get_preset, format_list_countries,
8 format_list_exchanges, format_list_filter_operators, format_list_index_symbols,
9 format_list_industries, format_list_markets, format_list_presets, format_list_ratings,
10 format_list_sectors, format_rows_markdown,
11};
12pub use super::query::{
13 build_payload, custom_query, custom_query_payload_preview, get_top_movers, search_by_index,
14 search_crypto, search_forex, search_stocks, BuildPayloadOpts, CustomQueryOpts,
15 PayloadPreviewOpts, SearchStocksOpts,
16};
17pub use super::resolve::{
18 parse_asset, parse_f64_range, resolve_index_wires, resolve_market_wires, resolve_sector_wires,
19};
20
21#[cfg(test)]
22mod tests {
23 use super::*;
24 use crate::field::Asset;
25 use crate::filter::FilterOperator;
26
27 #[test]
28 fn parse_ops_and_asset() {
29 assert_eq!(
30 FilterOperator::from_wire(">="),
31 Some(FilterOperator::AboveOrEqual)
32 );
33 assert_eq!(
34 FilterOperator::from_wire("in_range"),
35 Some(FilterOperator::InRange)
36 );
37 assert_eq!(parse_asset("crypto").unwrap(), Asset::Crypto);
38 assert!(parse_asset("nope").is_err());
39 }
40
41 #[test]
42 fn discover_and_presets_offline() {
43 let text = format_discover_fields(Asset::Crypto, "rsi", 5);
44 assert!(text.contains("RSI") || text.contains("fields matching"));
45 assert!(format_list_presets().contains("crypto_price"));
46 assert!(format_get_preset("crypto_price").unwrap().contains("Name"));
47 assert!(format_field_types(Asset::Stock).contains("**price**"));
48 assert!(format_list_sectors().contains("TECHNOLOGY_SERVICES"));
49 assert!(format_list_sectors().contains("Technology Services"));
50 assert!(format_list_countries().contains("UNITED_STATES"));
51 assert!(format_list_industries().contains("SEMICONDUCTORS"));
52 assert!(format_list_exchanges().contains("NASDAQ"));
53 assert!(format_list_ratings().contains("STRONG_BUY"));
54 assert!(format_list_filter_operators().contains("in_range"));
55 assert!(format_list_filter_operators().contains("PRICE"));
56 assert!(format_list_filter_operators().contains("Technology Services"));
57 assert!(
58 format_list_markets().contains("AMERICA") || format_list_markets().contains("america")
59 );
60 assert!(format_list_index_symbols().contains("SP500"));
61 assert!(format_list_index_symbols().contains("SP;SPX"));
62 }
63
64 #[test]
65 fn custom_payload_preview_merges_filters() {
66 let payload = custom_query_payload_preview(&PayloadPreviewOpts {
67 asset_type: "stock",
68 fields: Some("NAME,PRICE"),
69 filters: Some(
70 r#"[{"field":"PRICE","op":">","value":50},{"field":"RSI","op":"in_range","value":[30,70]}]"#,
71 ),
72 sort_by: Some("PRICE"),
73 ascending: false,
74 limit: 10,
75 indices: None,
76 markets: None,
77 })
78 .unwrap();
79 assert!(payload["columns"].as_array().unwrap().len() >= 2);
80 assert_eq!(payload["range"], serde_json::json!([0, 10]));
81 let filters = payload["filter"].as_array().unwrap();
82 assert!(filters
83 .iter()
84 .any(|f| f["left"] == "close" || f["operation"] == "greater"));
85 }
86
87 #[test]
88 fn build_payload_with_index_and_markets() {
89 let text = build_payload(&BuildPayloadOpts {
90 asset_type: "stock",
91 fields: Some("NAME,PRICE"),
92 filters: None,
93 sort_by: Some("MARKET_CAPITALIZATION"),
94 indices: Some("SP500,NASDAQ_100"),
95 markets: Some("AMERICA"),
96 })
97 .unwrap();
98 assert!(text.contains("SYML:SP;SPX"));
99 assert!(text.contains("SYML:NASDAQ;NDX"));
100 assert!(text.contains("america"));
101 assert_eq!(resolve_index_wires(Some("SP;SPX")).unwrap(), vec!["SP;SPX"]);
102 assert_eq!(
103 resolve_index_wires(Some("SYML:SP;SPX")).unwrap(),
104 vec!["SP;SPX"]
105 );
106 assert_eq!(resolve_index_wires(Some("SP500")).unwrap(), vec!["SP;SPX"]);
107 assert_eq!(
108 resolve_market_wires(Some("america")).unwrap(),
109 vec!["america"]
110 );
111 assert!(resolve_index_wires(Some("NOPE")).is_err());
112 }
113
114 #[test]
115 fn payload_preview_indices_emit_syml_symbolset() {
116 let payload = custom_query_payload_preview(&PayloadPreviewOpts {
117 asset_type: "stock",
118 fields: Some("NAME,PRICE"),
119 filters: None,
120 sort_by: None,
121 ascending: false,
122 limit: 5,
123 indices: Some("SP500"),
124 markets: Some("AMERICA"),
125 })
126 .unwrap();
127 assert_eq!(
128 payload["symbols"]["symbolset"],
129 serde_json::json!(["SYML:SP;SPX"])
130 );
131 assert_eq!(payload["markets"], serde_json::json!(["america"]));
132 }
133
134 #[test]
135 fn format_rows_markdown_empty() {
136 assert!(format_rows_markdown(&[], 5).contains("No results"));
137 }
138}