返回 last30days-skill
test_instagram.py
根目录 / tests / test_instagram.py
1 import unittest
2
3 from lib.instagram import _parse_items
4
5
6 class TestInstagramOwnerTypeSafety(unittest.TestCase):
7 def _make_raw(self, **overrides):
8 base = {
9 "id": "1",
10 "code": "ABC123",
11 "caption": "test caption",
12 "owner": {"username": "testuser"},
13 }
14 base.update(overrides)
15 return base
16
17 def test_owner_as_dict(self):
18 items = _parse_items([self._make_raw()], "test")
19 self.assertEqual("testuser", items[0]["author_name"])
20
21 def test_owner_as_string(self):
22 items = _parse_items([self._make_raw(owner="stringuser")], "test")
23 self.assertEqual("stringuser", items[0]["author_name"])
24
25 def test_owner_missing(self):
26 raw = self._make_raw()
27 del raw["owner"]
28 items = _parse_items([raw], "test")
29 self.assertEqual("", items[0]["author_name"])
30
31 def test_owner_none(self):
32 items = _parse_items([self._make_raw(owner=None)], "test")
33 self.assertEqual("", items[0]["author_name"])
34
35 def test_user_field_fallback(self):
36 raw = self._make_raw()
37 del raw["owner"]
38 raw["user"] = {"username": "fallbackuser"}
39 items = _parse_items([raw], "test")
40 self.assertEqual("fallbackuser", items[0]["author_name"])
41
42
43 class TestInstagramComments(unittest.TestCase):
44 """U1: Instagram comment fetching via ScrapeCreators."""
45
46 def test_fetch_post_comments_parses_and_sorts_by_likes(self):
47 from unittest.mock import patch
48 from lib import instagram
49
50 fake = {
51 "success": True,
52 "comments": [
53 {"text": "mid", "comment_like_count": 3,
54 "created_at": "2026-07-04T14:27:58.000Z", "user": {"username": "bob"}},
55 {"text": "gold", "comment_like_count": 500,
56 "created_at": "2026-07-03T10:00:00.000Z", "user": {"username": "alice"}},
57 {"text": "", "comment_like_count": 999,
58 "created_at": "2026-07-02T10:00:00.000Z", "user": {"username": "skip"}},
59 ],
60 "cursor": None,
61 }
62 with patch.object(instagram.http, "get", return_value=fake):
63 out = instagram._fetch_post_comments(
64 "https://www.instagram.com/reel/ABC/", token="k", max_comments=5,
65 )
66 # Empty-text dropped; sorted desc by comment_like_count.
67 self.assertEqual([c["text"] for c in out], ["gold", "mid"])
68 self.assertEqual(out[0]["comment_like_count"], 500)
69 self.assertEqual(out[0]["author"], "alice")
70 self.assertEqual(out[0]["date"], "2026-07-03")
71
72 def test_fetch_post_comments_error_returns_empty(self):
73 from unittest.mock import patch
74 from lib import instagram
75
76 def _boom(*a, **k):
77 raise RuntimeError("network")
78
79 with patch.object(instagram.http, "get", side_effect=_boom):
80 out = instagram._fetch_post_comments("https://x/", token="k")
81 self.assertEqual(out, [])
82
83 def test_enrich_with_comments_no_token_or_items_noop(self):
84 from lib import instagram
85 self.assertEqual([], instagram.enrich_with_comments([], token="k"))
86 items = [{"url": "u", "engagement": {"likes": 5}}]
87 self.assertEqual(items, instagram.enrich_with_comments(items, token=""))
88 self.assertNotIn("top_comments", items[0])
89
90 def test_is_instagram_comments_available_gate(self):
91 from lib import env
92 self.assertFalse(env.is_instagram_comments_available({}))
93 self.assertFalse(env.is_instagram_comments_available(
94 {"SCRAPECREATORS_API_KEY": "k"})) # key but no INCLUDE_SOURCES
95 self.assertFalse(env.is_instagram_comments_available(
96 {"INCLUDE_SOURCES": "instagram_comments"})) # opt-in but no key
97 self.assertTrue(env.is_instagram_comments_available(
98 {"SCRAPECREATORS_API_KEY": "k", "INCLUDE_SOURCES": "tiktok,instagram_comments"}))
99
100
101 class TestExpandInstagramQueries(unittest.TestCase):
102 """Tests for expand_instagram_queries() multi-query generation."""
103
104 def test_default_depth_returns_two_plus_queries(self):
105 from lib.instagram import expand_instagram_queries
106 queries = expand_instagram_queries("Kanye West", "default")
107 self.assertGreaterEqual(len(queries), 2)
108 # Breaking_news intent should include reaction/edit variant
109 variant_found = any(
110 "reaction" in q.lower() or "edit" in q.lower()
111 for q in queries
112 )
113 self.assertTrue(variant_found, f"Expected reaction/edit variant: {queries}")
114
115 def test_quick_depth_returns_one_query(self):
116 from lib.instagram import expand_instagram_queries
117 queries = expand_instagram_queries("Kanye West", "quick")
118 self.assertEqual(len(queries), 1)
119
120 if __name__ == "__main__":
121 unittest.main()
122
122 lines PYTHON