# tests/test_top_line.py """T5: _top_line 看点行(theme_line 取数升级)测试。""" from __future__ import annotations import unittest from unittest import mock import daily.generate as g FEED_HIT = { "topTrending": [ {"title": "remotion-video", "source": "src", "description": "video tool"}, ], "topHot": [], } FEED_MISS = { "topTrending": [ {"title": "zzz-nomatch", "source": "src", "description": "nothing"}, ], "topHot": [], } class TopLineTests(unittest.TestCase): def test_scores_hit_returns_theme(self): # 命中 THEME_RULES(video) -> 评分最高主题 with mock.patch.object(g, "env_bool", return_value=True): line = g._top_line(FEED_HIT) self.assertIn("今日主题", line) self.assertIn("AI 多媒体", line) def test_fallback_to_theme_names_when_no_score(self): # 无评分命中但 theme_clusters 能聚类 -> 用主题名 feed = { "topTrending": [ {"id": "x", "title": "runcomfy-x", "source": "s", "description": "video x"}, ], "topHot": [], } with mock.patch.object(g, "env_bool", return_value=True): # 让评分落空(前 10 无命中)但 clusters(前 20)命中 line = g._top_line(feed) self.assertIn("今日主题", line) self.assertIn("AI 多媒体", line) def test_switch_off_uses_legacy_detect(self): # DAILY_WECOM_TOP_LINE=0 -> 退回 _detect_theme_line with mock.patch.object(g, "env_bool", return_value=False): line = g._top_line(FEED_MISS) self.assertEqual(line, g._detect_theme_line(FEED_MISS)) def test_empty_feed_hardcoded_fallback(self): # 完全无数据 -> 硬编码兜底, 不抛异常 with mock.patch.object(g, "env_bool", return_value=True): line = g._top_line({"topTrending": [], "topHot": []}) self.assertIn("今日主题", line) if __name__ == "__main__": unittest.main()