from __future__ import annotations from types import SimpleNamespace from app.api import screener as screener_api class _MonitorEngine: def __init__(self, results=None): self.results = results or {} def latest_strategy_results(self): return self.results def _request(tmp_path, monitor_results=None): repo = SimpleNamespace(store=SimpleNamespace(data_dir=tmp_path)) state = SimpleNamespace(repo=repo, monitor_engine=_MonitorEngine(monitor_results)) return SimpleNamespace(app=SimpleNamespace(state=state)) def test_cached_summary_omits_rows_and_counts_realtime_expirations(monkeypatch, tmp_path): cached = { "as_of": "2026-07-20", "results": { "strategy_a": { "as_of": "2026-07-20", "total": 2, "rows": [{"symbol": "000001.SZ"}, {"symbol": "000002.SZ"}], }, }, "today_ever_rows": { "strategy_a": { "000001.SZ": {"symbol": "000001.SZ"}, "600000.SH": {"symbol": "600000.SH"}, }, }, "updated_at": 1, } realtime = { "strategy_a": { "as_of": "2026-07-20", "total": 2, "rows": [{"symbol": "000002.SZ"}, {"symbol": "300001.SZ"}], }, } monkeypatch.setattr(screener_api.strategy_cache, "read_cache", lambda *_args: cached) payload = screener_api.get_cached_summary(_request(tmp_path, realtime)) assert payload["results"] == { "strategy_a": {"total": 2, "as_of": "2026-07-20", "computed_at": None} } assert payload["today_ever_counts"] == {"strategy_a": 4} assert "rows" not in payload["results"]["strategy_a"] def test_cached_result_returns_only_requested_rows_with_ext_and_strategy_membership(monkeypatch, tmp_path): cached = { "as_of": "2026-07-20", "results": { "strategy_a": { "as_of": "2026-07-20", "total": 1, "rows": [{"symbol": "000001.SZ"}], }, "strategy_b": { "as_of": "2026-07-20", "total": 2, "rows": [{"symbol": "000001.SZ"}, {"symbol": "600000.SH"}], }, }, "today_ever_rows": { "strategy_a": { "000001.SZ": {"symbol": "000001.SZ"}, "000002.SZ": {"symbol": "000002.SZ"}, }, }, "updated_at": 1, } monkeypatch.setattr(screener_api.strategy_cache, "read_cache", lambda *_args: cached) monkeypatch.setattr( screener_api, "_load_ext_value_maps", lambda *_args: {"concept.concept": {"000001.SZ": "银行", "000002.SZ": "科技"}}, ) payload = screener_api.get_cached_result( "strategy_a", _request(tmp_path), ext_columns="concept.concept", ) assert payload["result"]["strategy"] == "strategy_a" assert payload["result"]["rows"] == [{"symbol": "000001.SZ", "concept.concept": "银行"}] assert payload["today_ever_rows"]["000002.SZ"]["concept.concept"] == "科技" assert payload["strategy_ids_by_symbol"] == {"000001.SZ": ["strategy_a", "strategy_b"]}