返回 last30days-skill
test_reddit_dedicated.py
根目录 / tests / test_reddit_dedicated.py
1 """Tests for the dedicated-subreddit lane in reddit_keyless (U1).
2
3 A dedicated subreddit (the entity's home, e.g. r/Kanye for "Kanye West") is
4 wholly on-topic: pulled in full via top+hot+new listings and exempt from the
5 relevance floor, so an on-topic post whose title lacks the entity name is kept.
6 """
7
8 from unittest import mock
9
10 from lib import reddit_keyless
11
12
13 def _post(i, date="2026-05-20", rel=0.0):
14 url = f"https://www.reddit.com/r/test/comments/{i:06d}/post_{i}/"
15 return {
16 "id": "", "title": f"Post {i}", "url": url, "score": 0, "num_comments": 0,
17 "subreddit": "test", "created_utc": None, "author": "u", "selftext": "",
18 "date": date, "engagement": {"score": 0, "num_comments": 0, "upvote_ratio": None},
19 "relevance": rel, "why_relevant": "Reddit search", "metadata": {},
20 }
21
22
23 def _listing_post(i, score, title, rel=0.0):
24 p = _post(i, rel=rel)
25 p["title"] = title
26 p["score"] = score
27 p["engagement"]["score"] = score
28 p["why_relevant"] = "Reddit listing"
29 p["metadata"] = {"post_id": f"{i:06d}"}
30 return p
31
32
33 def _no_enrich():
34 return mock.patch.object(
35 reddit_keyless.reddit_shreddit, "fetch_comments",
36 return_value={"top_comments": [], "comment_insights": [], "num_comments": None},
37 )
38
39
40 class TestDedicatedLane:
41 def test_dedicated_listings_pulled_with_top_hot_new_and_marked(self):
42 ded = _listing_post(1, 2643, "What the actual fuck is this ye?")
43 ded["subreddit"] = "Kanye" # Match the requested dedicated subreddit.
44 captured = {}
45
46 def fake_fetch(subs, depth="default", query="", sorts=None):
47 if sorts == reddit_keyless.DEDICATED_SORTS:
48 captured["sorts"] = sorts
49 captured["subs"] = subs
50 return [ded]
51 return []
52
53 with mock.patch.object(reddit_keyless.reddit_listing, "fetch_listings",
54 side_effect=fake_fetch), \
55 mock.patch.object(reddit_keyless.reddit_arctic, "fetch_listings",
56 return_value=[]), \
57 mock.patch.object(reddit_keyless.reddit_search, "search",
58 return_value=[]) as search:
59 out = reddit_keyless._discover("Kanye West", "default", None,
60 dedicated_subreddits=["Kanye"])
61 # Dedicated subs keep their full-listing lane; no per-sub search for them.
62 assert search.call_args.kwargs["subreddits"] is None
63 assert captured["sorts"] == ["top", "hot", "new"]
64 assert captured["subs"] == ["Kanye"]
65 assert len(out) == 1
66 assert out[0]["dedicated"] is True
67
68 def test_dedicated_post_survives_floor_without_entity_name(self):
69 # On-topic dedicated post whose title lacks "Kanye" (relevance 0) must be
70 # kept; off-topic non-dedicated posts (relevance 0) are floored out.
71 ded = _listing_post(1, 2284, "There's 2 types of people", rel=0.0)
72 ded["dedicated"] = True
73 offtopic = [_post(10 + i, rel=0.0) for i in range(5)]
74 with mock.patch.object(reddit_keyless, "_discover", return_value=[ded] + offtopic), \
75 _no_enrich():
76 out = reddit_keyless.search_and_enrich("Kanye West", "2026-05-01", "2026-05-31")
77 urls = {p["url"] for p in out}
78 assert ded["url"] in urls # dedicated kept despite relevance 0
79 assert all(o["url"] not in urls for o in offtopic) # off-topic floored
80
81 def test_dedicated_dedup_keeps_floor_exempt_status(self):
82 # A thread present in both the dedicated lane and a broad listing keeps
83 # its dedicated (floor-exempt) flag — dedicated is merged first.
84 shared_ded = _listing_post(1, 500, "fresh thread", rel=0.0)
85 shared_ded["subreddit"] = "Kanye" # Match the requested dedicated subreddit.
86 shared_broad = _listing_post(1, 500, "fresh thread", rel=0.0) # same url/id
87 shared_broad["subreddit"] = "hiphopheads" # Match the requested broad subreddit.
88
89 def fake_fetch(subs, depth="default", query="", sorts=None):
90 return [shared_ded] if sorts == reddit_keyless.DEDICATED_SORTS else [shared_broad]
91
92 with mock.patch.object(reddit_keyless.reddit_listing, "fetch_listings",
93 side_effect=fake_fetch), \
94 mock.patch.object(reddit_keyless.reddit_search, "search", return_value=[]):
95 out = reddit_keyless._discover("Kanye West", "default", ["hiphopheads"],
96 dedicated_subreddits=["Kanye"])
97 same = [p for p in out if p["url"] == shared_ded["url"]]
98 assert len(same) == 1
99 assert same[0].get("dedicated") is True
100
101 def test_no_dedicated_subs_is_noop(self):
102 with mock.patch.object(reddit_keyless.reddit_search, "search",
103 return_value=[_post(1)]), \
104 mock.patch.object(reddit_keyless.reddit_listing, "fetch_listings",
105 return_value=[]):
106 out = reddit_keyless._discover("topic", "default", ["test"])
107 assert all(not p.get("dedicated") for p in out)
108
108 lines PYTHON