- 新增常驻调度器 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>
96 lines
3.3 KiB
Python
96 lines
3.3 KiB
Python
"""Tests for daily.featured_pick."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from daily.featured_pick import (
|
|
apply_featured_pick,
|
|
match_in_data,
|
|
parse_featured_pick,
|
|
pick_command_from_featured,
|
|
pick_why_from_featured,
|
|
research_featured_pick,
|
|
)
|
|
|
|
|
|
SAMPLE_INPUT = {
|
|
"skills_trending": [
|
|
{
|
|
"id": "foo/bar/gstack-cli",
|
|
"title": "gstack-cli",
|
|
"source": "foo/bar",
|
|
"installs": 1200,
|
|
"installs_fmt": "1.2K",
|
|
"link": "https://skills.sh/foo/bar/gstack-cli",
|
|
"description": "Agent workflow CLI",
|
|
}
|
|
],
|
|
"skills_hot": [],
|
|
"github_trending": [
|
|
{
|
|
"repo": "acme/gstack",
|
|
"url": "https://github.com/acme/gstack",
|
|
"total_stars_fmt": "3.2K",
|
|
"description": "GStack toolkit",
|
|
}
|
|
],
|
|
"github_emerging": [],
|
|
"github_topic": {"topic": "llm", "repos": []},
|
|
}
|
|
|
|
|
|
class ParseFeaturedPickTests(unittest.TestCase):
|
|
def test_empty(self):
|
|
with patch.dict(os.environ, {}, clear=True):
|
|
self.assertIsNone(parse_featured_pick())
|
|
|
|
def test_query_only(self):
|
|
with patch.dict(os.environ, {"DAILY_FEATURED_PICK": "gstack"}, clear=True):
|
|
self.assertEqual(parse_featured_pick(), {"query": "gstack"})
|
|
|
|
def test_query_with_url(self):
|
|
with patch.dict(os.environ, {"DAILY_FEATURED_PICK": "gstack|https://example.com"}, clear=True):
|
|
self.assertEqual(
|
|
parse_featured_pick(),
|
|
{"query": "gstack", "url_hint": "https://example.com"},
|
|
)
|
|
|
|
|
|
class MatchInDataTests(unittest.TestCase):
|
|
def test_matches_skill_and_github(self):
|
|
matches = match_in_data(SAMPLE_INPUT, "gstack")
|
|
self.assertEqual(len(matches["skills"]), 1)
|
|
self.assertEqual(matches["skills"][0]["title"], "gstack-cli")
|
|
self.assertEqual(len(matches["github"]), 1)
|
|
self.assertEqual(matches["github"][0]["repo"], "acme/gstack")
|
|
|
|
|
|
class FeaturedPickWorkflowTests(unittest.TestCase):
|
|
def test_fallback_without_llm(self):
|
|
llm_input = dict(SAMPLE_INPUT)
|
|
with patch.dict(os.environ, {"DAILY_FEATURED_PICK": "gstack"}, clear=True):
|
|
with patch("daily.featured_pick.has_llm_configured", return_value=False):
|
|
featured = research_featured_pick(llm_input, date_str="2026-07-03")
|
|
self.assertIsNotNone(featured)
|
|
assert featured is not None
|
|
self.assertEqual(featured["type"], "skill")
|
|
self.assertIn("npx skills add foo/bar/gstack-cli", featured["command"])
|
|
self.assertTrue(featured["why_today"])
|
|
|
|
def test_apply_featured_pick_mutates_input(self):
|
|
llm_input = dict(SAMPLE_INPUT)
|
|
with patch.dict(os.environ, {"DAILY_FEATURED_PICK": "gstack"}, clear=True):
|
|
with patch("daily.featured_pick.has_llm_configured", return_value=False):
|
|
featured = apply_featured_pick(llm_input, date_str="2026-07-03")
|
|
self.assertIsNotNone(featured)
|
|
self.assertIn("featured_pick", llm_input)
|
|
self.assertEqual(pick_command_from_featured(featured), llm_input["featured_pick"]["command"])
|
|
self.assertEqual(pick_why_from_featured(featured), llm_input["featured_pick"]["why_today"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|