from __future__ import annotations import unittest from pathlib import Path from server import DashboardService from tests.frontend_test_helpers import ( assembled_frontend_runtime, assembled_frontend_document, ) class SearchDatabaseStub: def __init__(self) -> None: self.directory = { "schema_version": 2, "items": [ { "id": "881107.TI", "code": "881107.TI", "name": "油气开采及服务", "type": "sector", "subtitle": "行业板块", "member_count": 19, }, { "id": "885728.TI", "code": "885728.TI", "name": "人工智能", "type": "theme", "subtitle": "概念题材", "member_count": 1079, }, ], } def get_data_snapshot(self, kind: str, cache_key: str): if (kind, cache_key) == ("search_directory", "ths"): return self.directory return None @staticmethod def search_stock_master(query: str, limit: int = 12): if query in {"002141", "贤丰控股"}: return [ { "ts_code": "002141.SZ", "code": "002141", "name": "贤丰控股", "industry": "元件", "market": "主板", "list_date": "20071228", } ] return [] class GlobalSearchTests(unittest.TestCase): def setUp(self) -> None: self.service = DashboardService.__new__(DashboardService) self.service.database = SearchDatabaseStub() self.service._system_credentials = {"tushare_token": ""} def test_search_groups_stock_sector_theme_and_index(self): stock = self.service.search_entities("002141", "2026-07-22") sector = self.service.search_entities("油气", "2026-07-22") theme = self.service.search_entities("人工智能", "2026-07-22") index = self.service.search_entities("上证指数", "2026-07-22") self.assertEqual(stock["groups"]["stocks"][0]["name"], "贤丰控股") self.assertEqual(stock["groups"]["stocks"][0]["industry"], "元件") self.assertEqual(sector["groups"]["sectors"][0]["code"], "881107.TI") self.assertEqual(theme["groups"]["themes"][0]["code"], "885728.TI") self.assertEqual(index["groups"]["indices"][0]["code"], "000001.SH") def test_empty_query_returns_all_groups_without_remote_lookup(self): result = self.service.search_entities("", "2026-07-22") self.assertEqual( result["groups"], {"stocks": [], "sectors": [], "themes": [], "indices": []}, ) def test_frontend_reuses_full_stock_detail_and_renders_market_daily_k(self): static_dir = Path(__file__).resolve().parents[1] / "frontend" html = assembled_frontend_document() script = assembled_frontend_runtime() self.assertIn('id="globalSearchButton"', html) self.assertIn('id="globalSearchDialog"', html) self.assertIn('id="entityDetailDialog"', html) self.assertIn("行情走势", html) self.assertIn('data-entity-detail-chart="daily"', html) self.assertIn('data-entity-detail-chart="intraday"', html) self.assertIn('event.key.toLowerCase() !== "k"', script) self.assertIn('openStock(item.id, { code: item.code', script) self.assertNotIn('include_notes', script) self.assertIn('const candles = (series || [])', script) self.assertIn('renderStockNotes(payload.notes || [])', script) if __name__ == "__main__": unittest.main()