from __future__ import annotations from types import SimpleNamespace import unittest from backend.symbol_utils import ( assemble_market_peer_payload, build_market_peer_candidates, search_symbols_catalog, ) class SymbolUtilsTests(unittest.TestCase): def setUp(self) -> None: self.symbols = { "BTCUSD": SimpleNamespace( symbol="BTCUSD", label="Bitcoin", label_en="Bitcoin", category="Crypto", description="BTC spot proxy", ), "ETHUSD": SimpleNamespace( symbol="ETHUSD", label="Ethereum", label_en="Ethereum", category="Crypto", description="ETH spot proxy", ), "XAUUSD": SimpleNamespace( symbol="XAUUSD", label="Vang", label_en="Gold", category="Kim loai", description="Gold spot", ), } def test_search_symbols_catalog_scores_exact_match_highest(self) -> None: payload = search_symbols_catalog(self.symbols, "BTCUSD") self.assertEqual(payload["count"], 1) self.assertEqual(payload["results"][0]["symbol"], "BTCUSD") self.assertEqual(payload["results"][0]["score"], 100) def test_build_market_peer_candidates_prefers_same_category(self) -> None: payload = build_market_peer_candidates(self.symbols, "BTCUSD", 2) peer_symbols = [peer.symbol for peer in payload["peer_configs"]] self.assertEqual(payload["category"], "Crypto") self.assertEqual(payload["symbol"], "BTCUSD") self.assertIn("ETHUSD", peer_symbols) def test_assemble_market_peer_payload_maps_ticker_results(self) -> None: peer_configs = [self.symbols["ETHUSD"], self.symbols["XAUUSD"]] peer_results = [{"price": 123.0, "change_pct": 4.5}, RuntimeError("down")] payload = assemble_market_peer_payload("Crypto", "BTCUSD", peer_configs, peer_results) self.assertEqual(payload["count"], 2) self.assertEqual(payload["peers"][0]["price"], 123.0) self.assertEqual(payload["peers"][0]["change_24h"], 4.5) self.assertEqual(payload["peers"][1]["price"], 0.0) if __name__ == "__main__": unittest.main()