SilverElixir commited on
Commit
db6342b
·
1 Parent(s): 73ec2bd

Cover kill-switch note, daily-limit boundary and whole-line cut

Browse files
tests/test_bot_search.py CHANGED
@@ -59,3 +59,46 @@ def test_empty_fallback_search_marks_reply_without_live_search(rate_guard_setup,
59
  sent_text = bot._safe_reply.await_args[0][1]
60
  assert "without live web search" in sent_text
61
  bot.chat_state.pop(123, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  sent_text = bot._safe_reply.await_args[0][1]
60
  assert "without live web search" in sent_text
61
  bot.chat_state.pop(123, None)
62
+
63
+
64
+ def test_disabled_search_marks_reply_without_live_search(rate_guard_setup, monkeypatch):
65
+ # Ревью: выключенный свитч при мёртвой квоте молча отвечал по памяти — пометка обязана быть.
66
+ message = rate_guard_setup()
67
+ message.text = "погугли что происходит с ДЦ Яндекса"
68
+ _kill_search_quota(monkeypatch)
69
+ monkeypatch.setenv("WEB_SEARCH_ENABLED", "0")
70
+
71
+ async def fake_fetch(query, *, timeout_sec=None, max_results=None):
72
+ raise AssertionError("fetch must not run while disabled")
73
+
74
+ async def fake_run_route(chat_id, ai_prompt, route, message, **kwargs):
75
+ return "ok", False
76
+
77
+ monkeypatch.setattr("lumen_message_core.fetch_web_snippets", fake_fetch)
78
+ monkeypatch.setattr(bot, "_run_route", fake_run_route)
79
+ asyncio.run(bot._handle_message_core(message))
80
+ sent_text = bot._safe_reply.await_args[0][1]
81
+ assert "without live web search" in sent_text
82
+ bot.chat_state.pop(123, None)
83
+
84
+
85
+ def test_daily_limit_keeps_note_and_skips_external_search(rate_guard_setup, monkeypatch):
86
+ # Граница: дневной лимит пользователя — честная пометка без чужого поиска
87
+ # (лимит именно его, обходить поиском нельзя) и без единого сетевого вызова в тестах.
88
+ message = rate_guard_setup()
89
+ message.text = "погугли что происходит с ДЦ Яндекса"
90
+ monkeypatch.setattr(bot, "_user_daily_gemini_exhausted", lambda uid, entry: True)
91
+
92
+ async def fake_fetch(query, *, timeout_sec=None, max_results=None):
93
+ raise AssertionError("fetch must not run on daily user limit")
94
+
95
+ async def fake_run_route(chat_id, ai_prompt, route, message, **kwargs):
96
+ assert all(p != "gemini" for p, _ in route)
97
+ return "ok", False
98
+
99
+ monkeypatch.setattr("lumen_message_core.fetch_web_snippets", fake_fetch)
100
+ monkeypatch.setattr(bot, "_run_route", fake_run_route)
101
+ asyncio.run(bot._handle_message_core(message))
102
+ sent_text = bot._safe_reply.await_args[0][1]
103
+ assert sent_text.startswith("Answering without web search")
104
+ bot.chat_state.pop(123, None)
tests/test_lumen_search.py CHANGED
@@ -58,6 +58,18 @@ def test_format_snippets_for_prompt_marks_data_and_skips_empties():
58
  assert lumen_search.format_snippets_for_prompt([{"title": "", "url": "", "snippet": ""}]) == ""
59
 
60
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  def test_route_has_live_search_follows_grounding_flags():
62
  assert lumen_search.route_has_live_search([("groq", "qwen/qwen3.8-27b")]) is False
63
  assert lumen_search.route_has_live_search([("gemini", "gemini-3.8-flash")]) is False
 
58
  assert lumen_search.format_snippets_for_prompt([{"title": "", "url": "", "snippet": ""}]) == ""
59
 
60
 
61
+ def test_format_snippets_for_prompt_cuts_on_whole_lines():
62
+ # Ревью: срез на 1500 символах рвал URL посередине — режем по целым строкам.
63
+ long_snippets = [
64
+ {"title": f"Title {i} " + "x" * 400, "url": f"https://example.com/{i}", "snippet": "y" * 400}
65
+ for i in range(10)
66
+ ]
67
+ block = lumen_search.format_snippets_for_prompt(long_snippets)
68
+ assert len(block) <= lumen_search._BLOCK_MAX_CHARS
69
+ assert block.endswith(")")
70
+ assert "https://example.com/9" not in block
71
+
72
+
73
  def test_route_has_live_search_follows_grounding_flags():
74
  assert lumen_search.route_has_live_search([("groq", "qwen/qwen3.8-27b")]) is False
75
  assert lumen_search.route_has_live_search([("gemini", "gemini-3.8-flash")]) is False