返回 last30days-skill
test_polymarket_disambiguation.py
根目录 / tests / test_polymarket_disambiguation.py
1 """Tests for --polymarket-keywords filter and filter_items_against_keywords."""
2
3 from __future__ import annotations
4
5 import unittest
6
7 from lib import polymarket
8
9
10 def _item(title: str) -> dict:
11 return {"title": title}
12
13
14 class FilterItemsAgainstKeywordsTests(unittest.TestCase):
15 def test_no_keywords_returns_all(self):
16 items = [_item("NBA Finals"), _item("Glasgow Warriors")]
17 out = polymarket.filter_items_against_keywords(items, [])
18 self.assertEqual(out, items)
19
20 def test_single_keyword_filters(self):
21 items = [
22 _item("Golden State Warriors win title"),
23 _item("Glasgow Warriors rugby"),
24 _item("Honor of Kings: Rogue Warriors"),
25 ]
26 out = polymarket.filter_items_against_keywords(items, ["golden"])
27 self.assertEqual(len(out), 1)
28 self.assertIn("Golden State", out[0]["title"])
29
30 def test_multiple_keywords_any_match(self):
31 items = [
32 _item("NBA Finals: Warriors vs Celtics"),
33 _item("Glasgow rugby"),
34 _item("GSW schedule"),
35 ]
36 out = polymarket.filter_items_against_keywords(items, ["nba", "gsw"])
37 self.assertEqual(len(out), 2)
38
39 def test_case_insensitive_match(self):
40 items = [_item("Golden State Warriors"), _item("GLASGOW WARRIORS")]
41 out = polymarket.filter_items_against_keywords(items, ["GOLDEN"])
42 self.assertEqual(len(out), 1)
43 self.assertIn("Golden State", out[0]["title"])
44
45 def test_empty_keyword_strings_ignored(self):
46 items = [_item("NBA Finals")]
47 out = polymarket.filter_items_against_keywords(items, ["", " ", ""])
48 # All keywords are empty → treated as no filter
49 self.assertEqual(out, items)
50
51 def test_sourceitem_like_objects(self):
52 class _SI:
53 def __init__(self, t):
54 self.title = t
55
56 items = [_SI("NBA Finals"), _SI("Glasgow Warriors rugby")]
57 out = polymarket.filter_items_against_keywords(items, ["nba"])
58 self.assertEqual(len(out), 1)
59 self.assertEqual(out[0].title, "NBA Finals")
60
61 def test_no_match_returns_empty(self):
62 items = [_item("Glasgow Warriors"), _item("Rogue Warriors")]
63 out = polymarket.filter_items_against_keywords(items, ["nba", "gsw"])
64 self.assertEqual(out, [])
65
66 if __name__ == "__main__":
67 unittest.main()
68
69
70 def test_acronym_title_matches_spelled_out_topic():
71 """A title abbreviating what the topic spells out must not be filtered.
72
73 Market titles use shorthand ("AGI by 2030?") while topics arrive spelled
74 out, so proportional word overlap scored zero on squarely on-topic markets.
75 """
76 assert polymarket._passes_topic_filter(
77 "artificial general intelligence",
78 "OpenAI announces it has achieved AGI before 2027?",
79 )
80 assert polymarket._passes_topic_filter("artificial general intelligence", "AGI by 2030?")
81
82
83 def test_acronym_credit_does_not_widen_the_filter():
84 """The acronym bridge must not rescue off-topic or weak single-word hits."""
85 assert not polymarket._passes_topic_filter(
86 "artificial general intelligence", "Premier League top scorer 2026"
87 )
88 assert not polymarket._passes_topic_filter(
89 "Mill.com food recycler", "Meek Mill announces tour"
90 )
91 assert polymarket._passes_topic_filter("AGI", "AGI by 2030?")
92 assert polymarket._passes_topic_filter("Kanye West", "Kanye West announces new album")
93
94
95 def test_similarity_scores_acronym_title_as_full_match():
96 """Clearing the topic filter is not enough: the relevance floor also drops it.
97
98 An on-topic market passed _passes_topic_filter and was then dropped by the
99 0.15 relevance floor, because the similarity scorer compared spelled-out
100 topic words against a shorthand title.
101 """
102 assert (
103 polymarket._compute_text_similarity(
104 "artificial general intelligence", "AGI by 2030?"
105 )
106 == 1.0
107 )
108 assert (
109 polymarket._compute_text_similarity(
110 "artificial general intelligence", "Premier League top scorer 2026"
111 )
112 == 0.0
113 )
114 assert (
115 polymarket._compute_text_similarity("Kanye West", "Kanye West announces new album")
116 == 1.0
117 )
118
119
120 def test_modifier_separated_acronym_matches_filter_and_similarity():
121 """A leading modifier must not change the initialism used by the scorer."""
122 topic = "impact of artificial general intelligence"
123 title = "AGI by 2030?"
124
125 assert polymarket._passes_topic_filter(topic, title)
126 assert polymarket._compute_text_similarity(topic, title) == 1.0
127
128
129 def test_two_letter_initialism_does_not_expand_topic():
130 """Ambiguous two-letter tokens must not receive full expanded-phrase relevance."""
131 topic = "machine learning"
132 title = "ML market cap above $1 billion?"
133
134 assert not polymarket._passes_topic_filter(topic, title)
135 assert polymarket._compute_text_similarity(topic, title) < 1.0
136
136 lines PYTHON