# tests/test_board_history.py from __future__ import annotations import json import os import tempfile import unittest from pathlib import Path from unittest.mock import patch from daily.board_history import extract_shown_keys, load_recent_shown_keys, merge_wecom_shown_into_data from daily.config import board_dedup_days, news_backfill_enabled class ConfigDiversityTests(unittest.TestCase): def test_board_dedup_days_default(self): with patch.dict(os.environ, {}, clear=True): self.assertEqual(board_dedup_days(), 7) def test_news_backfill_default_off(self): with patch.dict(os.environ, {}, clear=True): self.assertFalse(news_backfill_enabled()) class ShownKeysTests(unittest.TestCase): def test_extract_github_repo_keys(self): items = [{"repo": "a/b"}, {"repo": "c/d"}] self.assertEqual(extract_shown_keys("github_trending", items), ["a/b", "c/d"]) def test_extract_skill_keys_include_source(self): items = [ { "id": "open.feishu.cn/lark-drive", "source": "open.feishu.cn", "title": "lark-drive", } ] self.assertEqual( extract_shown_keys("skills_trending", items), ["open.feishu.cn/lark-drive", "open.feishu.cn"], ) def test_load_recent_reads_wecom_shown_not_baseline(self): with tempfile.TemporaryDirectory() as tmp: out = Path(tmp) # 前日:shown 只有 x/y;baseline raw 含 a/b —— 周去重只能看到 x/y payload = { "data": { "date": "2026-07-13", "movement_baseline": { "github_trending": [{"repo": "a/b"}, {"repo": "x/y"}], }, "wecom_shown_keys": {"github_trending": ["x/y"]}, } } (out / "2026-07-13.data.json").write_text( json.dumps(payload, ensure_ascii=False), encoding="utf-8" ) with patch("daily.board_history.OUTPUT_DIR", out): keys = load_recent_shown_keys("2026-07-14", lookback_days=7) self.assertEqual(keys["github_trending"], {"x/y"}) self.assertNotIn("a/b", keys["github_trending"]) def test_load_recent_falls_back_to_wecom_md_when_shown_missing(self): """旧日 data 无 wecom_shown_keys 时,从同日 wecom.md 解析实际展示 keys。""" with tempfile.TemporaryDirectory() as tmp: out = Path(tmp) payload = { "data": { "date": "2026-07-13", "github_trending": [{"repo": "other/top"}], } } (out / "2026-07-13.data.json").write_text( json.dumps(payload, ensure_ascii=False), encoding="utf-8" ) (out / "2026-07-13.wecom.md").write_text( "\n".join( [ "🐙 **GitHub Trending Top 2**", "1. [vinta/awesome-python](https://github.com/vinta/awesome-python)", "2. [react/react](https://github.com/react/react)", "", "🌱 **GitHub 新兴 Top 1**", "1. [elder-plinius/T3MP3ST](https://github.com/elder-plinius/T3MP3ST)", ] ), encoding="utf-8", ) with patch("daily.board_history.OUTPUT_DIR", out): keys = load_recent_shown_keys("2026-07-14", lookback_days=7) self.assertEqual( keys["github_trending"], {"vinta/awesome-python", "react/react"}, ) self.assertEqual(keys["github_emerging"], {"elder-plinius/T3MP3ST"}) self.assertNotIn("other/top", keys["github_trending"]) def test_merge_shown_does_not_touch_baseline(self): data = { "movement_baseline": {"github_trending": [{"repo": "raw/one"}]}, } merged = merge_wecom_shown_into_data( data, {"github_trending": ["shown/one"]} ) self.assertEqual( merged["movement_baseline"]["github_trending"][0]["repo"], "raw/one" ) self.assertEqual(merged["wecom_shown_keys"]["github_trending"], ["shown/one"]) def test_persist_shown_keys_differs_from_baseline_keys(self): from daily.board_select import board_select raw = [{"repo": f"o/r{i}"} for i in range(10)] recent = {f"o/r{i}" for i in range(3)} selected = board_select( board="github_trending", items=raw, recent_keys=recent, limit=5, pool_size=50, kind="github", ) baseline_keys = [x["repo"] for x in raw[:5]] shown = extract_shown_keys("github_trending", selected) data = { "movement_baseline": { "github_trending": [{"repo": k} for k in baseline_keys], }, } merged = merge_wecom_shown_into_data(data, {"github_trending": shown}) self.assertNotEqual( set(merged["wecom_shown_keys"]["github_trending"]), {x["repo"] for x in merged["movement_baseline"]["github_trending"]}, ) self.assertEqual(shown, ["o/r3", "o/r4", "o/r5", "o/r6", "o/r7"]) if __name__ == "__main__": unittest.main()