from __future__ import annotations from datetime import datetime, timezone from daily.news.rank import ( apply_news_ranking, fuzzy_dedupe_by_title, jaccard_similarity, score_news_item, _title_tokens, ) def test_jaccard_similarity_detects_duplicate_headlines(): left = _title_tokens("OpenAI launches GPT-5 with new reasoning") right = _title_tokens("OpenAI launches GPT 5 with reasoning upgrade") assert jaccard_similarity(left, right) >= 0.55 def test_fuzzy_dedupe_keeps_higher_score(): items = [ {"title": "OpenAI launches GPT-5", "link": "https://a.example/1", "score": 20}, {"title": "OpenAI launches GPT 5 today", "link": "https://b.example/2", "score": 45}, ] deduped = fuzzy_dedupe_by_title(items, threshold=0.55) assert len(deduped) == 1 assert deduped[0]["link"] == "https://b.example/2" def test_score_news_item_prefers_fresh_official_and_penalizes_yesterday(): now = datetime(2026, 7, 3, 12, 0, tzinfo=timezone.utc) fresh = { "title": "Claude update", "link": "https://anthropic.com/news/claude", "category_id": "official", "published": "Thu, 03 Jul 2026 10:00:00 GMT", } stale_seen = { "title": "Old story", "link": "https://example.com/old", "category_id": "media", "published": "Mon, 30 Jun 2026 10:00:00 GMT", } fresh_score = score_news_item(fresh, yesterday_links=set(), now=now) stale_score = score_news_item( stale_seen, yesterday_links={"https://example.com/old"}, now=now, ) assert fresh_score > stale_score def test_apply_news_ranking_sets_flat_scores(monkeypatch, tmp_path): import daily.config as config import daily.news.rank as rank out = tmp_path / "output" out.mkdir() monkeypatch.setattr(config, "OUTPUT_DIR", out) monkeypatch.setattr(rank, "load_yesterday_news_links", lambda _date: set()) news = { "enabled": True, "categories": [ { "id": "official", "name": "厂商官方", "icon": "🏢", "items": [ { "title": "OpenAI ships new model", "link": "https://openai.com/a", "category_id": "official", "published": "Thu, 03 Jul 2026 08:00:00 GMT", }, { "title": "OpenAI ships a new model today", "link": "https://techcrunch.com/a", "category_id": "media", "published": "Thu, 03 Jul 2026 07:00:00 GMT", }, ], } ], "flat": [], "stats": {}, } ranked = apply_news_ranking(news, date_str="2026-07-03") assert ranked["flat"] assert all("score" in item for item in ranked["flat"]) assert len(ranked["flat"]) == 1