- 新增常驻调度器 daily/scheduler.py + run-scheduler.ps1(定时生成/推送) - 新增 daily/bridge_manager.py:Windows 兼容的 Cursor SDK 桥接 - 新增 skills/daily-featured-pick 首推 Skill 与叙事轴/去重逻辑 - 新闻抓取窗口、GitHub 搜索、企微 delta 模式等多项改进 - 补充设计文档与 superpowers 计划/规范 - 新增对应测试(scheduler、featured_pick、github_search、news_fetch_window 等) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
141 lines
5.4 KiB
Python
141 lines
5.4 KiB
Python
# 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()
|