"""AI 时讯 deep-research 解析与企微格式。""" from __future__ import annotations import unittest from daily.format_wecom import _ai_news_lines, replace_wecom_news_sections from daily.news.research import parse_research_response class TestAiNewsResearchParse(unittest.TestCase): def test_parse_items(self): raw = """ { "items": [ { "title": "Apple sues OpenAI", "link": "https://techcrunch.com/2026/07/10/apple/", "source_name": "TechCrunch", "desc_short": "苹果起诉 OpenAI 涉嫌窃取商业机密", "published_fmt": "07-11 05:00" } ] } """ items, tech = parse_research_response(raw, limit=10) self.assertEqual(len(items), 1) self.assertEqual(items[0]["source_name"], "TechCrunch") self.assertIn("苹果", items[0]["desc_short"]) self.assertEqual(tech, []) def test_dedupe_links(self): raw = """{"items": [ {"title": "A", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "一"}, {"title": "B", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "二"} ]}""" items, _ = parse_research_response(raw, limit=10) self.assertEqual(len(items), 1) def test_parse_tech_items(self): raw = """{"items": [ {"title": "A", "link": "https://example.com/a", "source_name": "Ex", "desc_short": "一"} ], "tech_items": [ {"title": "B", "link": "https://example.com/b", "source_name": "Ex", "desc_short": "二"} ]}""" items, tech = parse_research_response(raw, limit=10, tech_limit=5) self.assertEqual(len(items), 1) self.assertEqual(len(tech), 1) self.assertEqual(tech[0]["title"], "B") class TestMergedWecomNews(unittest.TestCase): def test_merged_block_format(self): items = [ { "title": "Apple sues OpenAI", "link": "https://techcrunch.com/x", "source_name": "TechCrunch", "desc_short": "苹果起诉 OpenAI", "published_fmt": "07-11 05:00", } ] lines = _ai_news_lines(items, merged=True) self.assertIn("TechCrunch - Apple sues OpenAI", lines[0]) self.assertIn("— 苹果起诉 OpenAI", lines[0]) self.assertNotIn("07-11", lines[0]) def test_merged_with_tech_block(self): md = """📰 **早报** 📈 **Skills Trending Top 1** 1. skill """ main = [ {"title": "Main", "link": "https://example.com/m", "source_name": "Src", "desc_short": "主条", "published_fmt": "07-11"} ] tech = [ {"title": "Tech", "link": "https://example.com/t", "source_name": "Src2", "desc_short": "技术条", "published_fmt": "07-12"} ] out = replace_wecom_news_sections(md, ai_news=main, tech_ai_news=tech, merged=True) self.assertIn("📰 **AI 时讯精选 Top 2**", out) self.assertNotIn("技术类时讯", out) self.assertNotIn("🔧", out) self.assertNotIn("07-11", out) self.assertNotIn("07-12", out) self.assertIn("2. [Src2 - Tech]", out) def test_replace_merged_removes_split_blocks(self): md = """📰 **早报** 🌍 **国际 AI 时讯 Top 1** 1. [old](https://example.com/old) · `X` 🇨🇳 **国内 AI 时讯 Top 1** 1. [old2](https://example.com/old2) · `Y` 📈 **Skills Trending Top 1** 1. skill """ items = [ { "title": "New story", "link": "https://example.com/new", "source_name": "Fortune", "desc_short": "新故事", "published_fmt": "", } ] out = replace_wecom_news_sections(md, ai_news=items, merged=True) self.assertIn("📰 **AI 时讯精选 Top 1**", out) self.assertNotIn("国际 AI 时讯", out) self.assertNotIn("国内 AI 时讯", out) self.assertIn("📈 **Skills Trending Top 1**", out) if __name__ == "__main__": unittest.main()