test(conftest): mute Telegram in all tests to stop prod leakage
A pytest run on prod was sending REAL Telegram messages to Slava: some tests (e.g. test_webhook_dedup advancing a stage) reach notify_stage_change -> send_telegram, which read the live .env token/chat_id and actually POSTed. Add an autouse fixture stubbing send_telegram to a no-op for every test. Patch the SOURCE src.notifications.send_telegram (covers all notify_* helpers and the many modules that do a local from .notifications import send_telegram inside functions) AND src.stage_engine.send_telegram (module-level binding, would not be intercepted by the source patch alone). webhooks/plane, launcher, queue_worker are patched defensively with raising=False. Verified: full suite run with FAKE telegram creds + an un-swallowable httpx.post trip-wire (BaseException, so send_telegram except Exception can not hide it) shows ZERO calls to api.telegram.org. Without the fixture the trip-wire fires, proving the guard is real.
This commit is contained in:
40
tests/conftest.py
Normal file
40
tests/conftest.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""Global pytest fixtures.
|
||||
|
||||
test(conftest): mute Telegram in ALL tests to stop prod leakage.
|
||||
|
||||
Background: a pytest run on prod was sending REAL Telegram messages to Slava,
|
||||
because some tests (e.g. test_webhook_dedup advancing a stage) reach
|
||||
notify_stage_change -> send_telegram, which reads the live .env
|
||||
telegram_bot_token/chat_id and actually POSTs to Telegram.
|
||||
|
||||
This autouse fixture stubs send_telegram to a no-op for every test:
|
||||
|
||||
- "src.notifications.send_telegram" is the SOURCE. All the notify_* helpers in
|
||||
notifications.py call the module-global send_telegram, and every other module
|
||||
that does a *local* `from .notifications import send_telegram` inside a
|
||||
function resolves it live at call time -> covered by patching the source.
|
||||
|
||||
- "src.stage_engine.send_telegram" is patched too, because stage_engine binds
|
||||
send_telegram as a MODULE-LEVEL name (from .notifications import send_telegram
|
||||
at import), so a patch of the source alone would not intercept its 3 direct
|
||||
calls. webhooks/plane and launcher import it locally inside functions, so the
|
||||
source patch already covers them; they are patched defensively with
|
||||
raising=False anyway in case that ever changes.
|
||||
|
||||
raising=False so a module that doesn't (yet) expose the name never breaks setup.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _no_telegram(monkeypatch):
|
||||
_noop = lambda *a, **k: None # noqa: E731
|
||||
# Source of truth (covers notifications.notify_* and all local re-imports).
|
||||
monkeypatch.setattr("src.notifications.send_telegram", _noop, raising=False)
|
||||
# Module-level binding in stage_engine (and defensive coverage elsewhere).
|
||||
monkeypatch.setattr("src.stage_engine.send_telegram", _noop, raising=False)
|
||||
monkeypatch.setattr("src.webhooks.plane.send_telegram", _noop, raising=False)
|
||||
monkeypatch.setattr("src.agents.launcher.send_telegram", _noop, raising=False)
|
||||
monkeypatch.setattr("src.queue_worker.send_telegram", _noop, raising=False)
|
||||
yield
|
||||
Reference in New Issue
Block a user